Material UI Stepper 在下一个或向后移动时不保持状态

问题描述 投票:0回答:4

我有

Material UI Stepper
组件。我在
stepper
按钮上动态渲染
ADD
。 每个步骤都包含一些表格,包括
TextFields, SelctBox etc.
当我在第一步填写表格并单击下一步在下一个屏幕上填写表格时,如果我通过单击
BACK Button
返回第一步,我将丢失第一步填写的数据。

所以问题是 - 当我们改变步骤时,有没有办法将数据保留在

Form Fields
中?

我尝试了下面,但不明白如何在父组件上存储状态。

export default function FeaturesSteppers(props) {

.......
const [stepperState, setStepperState] = React.useState({});

const getStepContent = step => {
switch (step) {
  case 0:
    return <Profile 
      index={index} 
      form={form} 
      stepperState={stepperState}
      onUpdateStepperState={handleUpdateStepper}
    />;
  case 1:
    return "< Step1 />";
  case 2:
    return "< Step2 />";
  case 3:
      return "< Step3 />";
  default:
    return "Unknown step";
}
}

.........

const handleUpdateStepper = (data) => {
  console.log('INSIDE Handle Update')
  setStepperState(...)
};

我不确定应该从

Profile.js
返回什么以及如何在父组件上使用它。

reactjs material-ui
4个回答
5
投票

代码的问题是,一旦从步骤 #0 转到步骤 #1 -

<Profile />
组件不再存在,并且所有子组件及其内部状态也不再存在。您可以将内部状态保存到某个全局状态/上下文中,一旦组件再次进入 DOM,它将重新加载内容,但您可以只渲染所有步骤,但隐藏不相关的步骤:

const getStepContent = step => {

    const allSteps = [
        <Profile 
            index={index} 
            form={form} 
            stepperState={stepperState}
            onUpdateStepperState={handleUpdateStepper}
        />,
        <Step1 />,
        <Step2 />,
        <Step3 />
    ];

    return (
        <>
            {allSteps.map(
                (stepCmp, index) => {
                    return <div hidden={index !== step}>{stepCmp}</dv>
                })
            }
        </>
    );
}

这里的缺点是您确实需要在实际显示所有组件之前渲染它们。


2
投票

你的问题已经 7 个月了,我也遇到了同样的问题,导致我来到这里。为了那些以后需要这个的人,这是我的修复方法。

  • 您必须确保所有
    <TextField/>
    输入值都是从您的父状态管理的。
  • 您必须将每个
    <TextField />
    的值作为 prop 传递给您的子组件。

考虑下面的例子:

   function Parent(){
      const [ values, setName ] = React.useState({
         name: "",
         email: "",
      });
      
      return (
         <Step1 inputValues = { values } />
      )
   }

然后你的子组件将如下所示:

   function Step1({ inputValues }){      
      return (
         <div>
            <TextField value={ inputValues.name } />
            <TextField value={ inputValues.email } />
         </div>
      )
   }

如果您导航离开并返回步进器索引,您的数据将保留。


2
投票

创建一个 useReducer() 函数并在其中存储所有初始状态,还使用上下文 api 将这些状态传递给您的子组件,并且每当您更改输入时,更新减速器状态。通过此您可以保留输入值


0
投票

这是我一起经历的事情。希望有帮助。

大纲:

  1. 创建面板组件(每个步骤一个)
  2. 定义步骤
  3. 创建管理状态的“步进组件”
  4. 在步进组件中使用“动态组件”来加载和传递状态

每项的更多详细信息如下所述。

  1. 面板组件

“面板”代表每个步骤的 UI。 使用标准 React 组件模式。

示例1:无状态传递

const Panel1 = (props) => {
  return <div>
    <p>
      Please share your thoughts to help us continue to make great products.  
    </p>
    <p >
        It only takes a minute to complete.
    </p>
  </div>;
};

示例2:传递状态

const Panel2 = (props) => {

  const {value, setValue} = props;  

  return (<div>
    <div >
      How helpful do you think this could be at your organization?
    </div>
    <textarea value={value} onChange={(event) => { setValue(event.target.value)}} />
  </div>);
};

  1. 定义步骤

那么,步骤只是一个简单的数组。

const steps = [  
    {     
      title: "What do you think?",
      panelName: 'Panel1'
    },
    {     
      title: "This one passes state",
      panelName: 'Panel1'
    },
]

  1. 创建管理状态的“步进组件” =================================================== ==== 关于此有很多指导,因此我不会重复这些文档。我想你已经走到这一步了。 但这些文档和这种方法之间存在三个独特的区别。 总结起来就是:
  • 定义状态 每个面板的所有状态都应在 Stepper 组件中定义。
  • 通过状态 步进器需要动态调用传入状态的组件
  • 动态组件 需要定义“动态组件”,它们动态加载您的面板。

以下是这三种技术的示例。

定义状态

为此的标准技术。例如,我的第二个面板有一个 TextArea 控件。我会这样定义状态,然后准备通过:

const [value, setValue] = useState("Text Area Example");

const panelState = {value, setValue };

显然你应该使用更具体的名称。根据需要创建任意数量。 那么是的,将所有状态捆绑到一个对象中。我选择将其称为 panelState。

捆绑状态(“panelState”)将在下面的“Pass State”中使用。
为了使其通用,我们使用以下方法传递所有状态和处理程序:{...panelState}

通过状态

在这里,我们动态加载您的面板并传递状态。
在我的情况下,当步进器向前或向后移动时,我会交换对话框的内容,如下所示:

<DialogContent>
      <Panel name={steps[activeStep].panelName} {...panelState}  />           
   </DialogContent>

要使其正常工作,您需要构建一个“动态组件”,即上面的面板。 下一节将向您展示如何操作。

动态组件

这就是魔法。 您的面板组件需要动态加载并将状态(和处理程序)传递到每个面板中。

const Panel = (props) => {
  const components = {
    'Panel1': Panel1,
    'Panel2': Panel2
  };

  const ComponentToRender = components[props.name];

  return (
    <>
      {ComponentToRender ? <ComponentToRender {...props} /> : null}
    </>
  );
}
 

就是这样。 希望您觉得这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.