状态从父级更改为子级,但未反映到React Hook中的TextField中
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状态从父级更改为子级,但未反映到React Hook中的TextField中相关的知识,希望对你有一定的参考价值。
我将组件(C)作为道具传递给父组件(A)内的子组件(B)。 A的状态也传递给C并映射到C的状态。但是,当我相应地更新A的状态和B的状态时,C的状态不会更新。
我的代码如下:(省略了导入语句)
const Parent = (props) => {
.............(other state)
const [info, setInfo] = React.useState(props.info);
const handleDataChanged = (d) => { setInfo(d); }
return (
<div>
........(other stuffs)
<MyModal
..........(other props)
body={ <MyComp data={ info } updateData={ handleDataChanged } /> }
/>
</div>
);
}
const MyModal = (props) => {
..........(other state)
const [content, setContent] = React.useState(props.body);
React.useEffect(() => { setContent(props.body); }, [props]);
return (
<Modal ...>
<div>{ content }</div>
</Modal>
);
}
const MyComp = (props) => {
const [data, setData] = React.useState(props.data);
React.useEffect(() => { setData(props.data); }, [props]);
return (
data && <TextField value={ data.name }
onChange={ e => {
let d = data;
d.name = e.target.value;
props.updateData(d); }} />
);
}
[当我在文本字段中键入内容时,我看到Parent
的info
已更改。 useEffect
的MyModal
未触发。并且data
中的MyComp
未更新。
更新:在进一步检查了上面的代码和下面的解决方案之后,问题仍然存在,但是我看到data
中的MyComp
确实从Parent
中获得了更改,但是TextField没有反映出来。
有人请教我如何从data
更新MyComp
并将其反映到Parent
。非常感谢!
实际上,您似乎正在尝试重新创建子级api https://reactjs.org/docs/react-api.html#reactchildren。
如果使用props.children来组成组件而不是上下传递props,则容易得多。
const MyModal = (props) => {
...(other state)
return (
<Modal>
<div>{ props.children }</div>
</Modal>
);
}
然后您可以直接在父级中处理功能,而不必将道具映射到状态(强烈建议)...
const Parent = (props) => {
...(other state)
const [info, setInfo] = React.useState(props.info);
const handleDataChanged = d => setInfo(d);
return (
<div>
...(other stuffs)
<MyModal {...props}>
<MyComp data={ info } updateData={ handleDataChanged } />
</MyModal>
</div>
);
}
此方法的优点是开销少得多。无需将状态A传递到C并映射到C的状态,您可以执行状态A(父组件)中的所有操作。不需要任何映射,您只有一个关于状态的真理来源,而且它更易于思考和建立。
或者,如果您想坚持当前的方法,只需在React.useEffect(() => { setContent(props.body); }, [props]);
中删除MyModal
并像这样直接映射道具
<Modal>
<div>{ props.body }</div>
</Modal>
我的代码的真正问题是:React Hook不知道状态对象中的特定属性或元素是否已更改。它仅知道整个对象是否已更改。
例如:如果您的状态中包含3个元素的数组或Json对象。如果数组中的一个元素更改,或者Json对象中的一个属性更改,React Hook将标识它们不变。
因此,要实际广播更改,必须将对象深度克隆为副本,然后将该副本设置回您的状态。为此,我使用lodash进行了深层克隆。
参考:https://dev.to/karthick3018/common-mistake-done-while-using-react-hooks-1foj
所以代码应该是:
在MyComp中:
onChange={e => { let d = _.cloneDeep(data); d.name = e.target.value; props.handleChange(d) }}
在父母中:
const handleChange = (data) => {
let d = _.cloneDeep(data);
setInfo(d);
}
然后按常规将handleChange作为委托传递给MyComp。
以上是关于状态从父级更改为子级,但未反映到React Hook中的TextField中的主要内容,如果未能解决你的问题,请参考以下文章
在 React-Router 中将状态作为道具从父级传递给子级?
在 useEffect() 钩子中从父级传递的子级调用函数,React