状态从父级更改为子级,但未反映到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); }} />
    );
}

[当我在文本字段中键入内容时,我看到Parentinfo已更改。 useEffectMyModal未触发。并且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

在 React 中将数据从父级传递给子级

Qt/C++ 将 worker 的父级更改为 qthread 失败

如何使引导树视图从父级折叠到子级?

如何从父级获取数据到子级?