繁体   English   中英

为什么即使使用钩子更新父 state 也不重新渲染子组件

[英]Why isn't child component re-rendered even though parent state is updated using hooks

我是 React 的新手,在使用 hook 时遇到了问题。 我将构建一个基本表单作为子组件,但我想知道为什么在更改其值时不呈现子表单上的输入元素。

这是我的代码。

'use strict';

function SearchForm({form, handleSearchFormChange}) {

    return (
        <div className="card border-0 bg-transparent">
            <div className="card-body p-0 pt-1">
                <div className="form-row">
                    <div className="col-auto">
                        <label className="mr-1" htmlFor="number">Number:</label>
                        <input type="text" className="form-control form-control-sm w-auto d-inline-block"
                               name="number" id="number" value={form.number} onChange={handleSearchFormChange}/>
                    </div>
                </div>
            </div>
        </div>
    );
}

function App() {
    const formDefault = {
        number: 'Initial Value'
    };
    const [form, setForm] = React.useState(formDefault);

    const handleSearchFormChange = (e) => {
        setForm(Object.assign(form, {[e.target.name]: e.target.value}));
        console.log('Handle Search Form Change', e.target.name, "=", e.target.value);
    };

    return (
        <React.Fragment>
            <div>Number : {form.number}</div>
            <SearchForm form={form} handleSearchFormChange={handleSearchFormChange} />
        </React.Fragment>
    );
}

const domContainer = document.querySelector('#root');
ReactDOM.render((
    <React.Fragment>
        <App/>
    </React.Fragment>
), domContainer);

我为父组件中的“数字”元素定义了一个 onChange 事件处理程序,并尝试使用道具将值传递给子组件。

问题是当我要更改“数字”时,“数字”输入元素根本没有改变。 (根本没有渲染)。 因此该输入元素始终具有“初始值”。 你能就此提出建议吗?

我想知道这种方法是否合理。

提前致谢。

反应的哲学之一是 state 是不可变的。 即,您不会更改现有 state object 的属性,而是创建一个新的 state ZA8CFFDE63911BD5B62ACZ6666。 这可以让反应告诉 state 通过简单的===检查前后发生了变化。

这行代码改变了现有的表格 object,然后将其传递给 setForm:

setForm(Object.assign(form, {[e.target.name]: e.target.value}));

所以 react 比较了setForm之前和之后的 object,发现它们是相同的 object。 因此,它得出的结论是没有任何变化,因此组件不会重新渲染。

相反,您需要制作 object 的副本并对副本进行更改。 如果您习惯于 Object.assign,则可以通过将空 object 作为第一个参数放入 Object.assign 来完成:

setForm(Object.assign({}, form, {[e.target.name]: e.target.value}));

或者,扩展语法是制作 object 的浅拷贝的便捷方法:

setForm({
  ...form,
  [e.target.name]: e.target.value
})

尝试替换setForm(Object.assign(form, {[e.target.name]: e.target.value}));

setForm(prevState => ({
    ...prevstate,
    [e.target.name]: e.target.value
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM