我有
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
返回什么以及如何在父组件上使用它。
代码的问题是,一旦从步骤 #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>
})
}
</>
);
}
这里的缺点是您确实需要在实际显示所有组件之前渲染它们。
你的问题已经 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>
)
}
如果您导航离开并返回步进器索引,您的数据将保留。
创建一个 useReducer() 函数并在其中存储所有初始状态,还使用上下文 api 将这些状态传递给您的子组件,并且每当您更改输入时,更新减速器状态。通过此您可以保留输入值
这是我一起经历的事情。希望有帮助。
大纲:
每项的更多详细信息如下所述。
“面板”代表每个步骤的 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>);
};
那么,步骤只是一个简单的数组。
const steps = [
{
title: "What do you think?",
panelName: 'Panel1'
},
{
title: "This one passes state",
panelName: 'Panel1'
},
]
以下是这三种技术的示例。
定义状态
为此的标准技术。例如,我的第二个面板有一个 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}
</>
);
}
就是这样。 希望您觉得这有帮助。