我是React的新手,使用钩子时遇到了问题。 我将构建一个基本表单作为子组件,但是我想知道为什么更改其值时子表单上的输入元素未呈现。
这是我的代码。
'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);
我为父组件中的'number'元素定义了一个onChange事件处理程序,并尝试使用prop将值传递给子组件。
问题在于,当我要更改“数字”时,“数字”输入元素完全没有更改。 (完全不渲染)。因此,该输入元素始终具有“初始值”。 您能为此建议吗?
我想知道这种方法是否合理。
谢谢。
答案 0 :(得分:2)
反应的哲学之一是状态是不变的。即,您不更改现有状态对象的属性,而是创建一个新的状态对象。这样可以做出反应,以通过之前和之后的简单===
检查来更改状态。
这行代码会更改现有的表单对象,然后将其传递给setForm:
setForm(Object.assign(form, {[e.target.name]: e.target.value}));
所以react比较setForm
之前和之后的对象,发现它们是同一对象。因此,得出的结论是什么都没有改变,因此该组件不会重新渲染。
相反,您需要制作对象的副本并在副本上进行更改。如果您习惯使用Object.assign,可以通过将一个空对象作为Object.assign的第一个参数来实现:
setForm(Object.assign({}, form, {[e.target.name]: e.target.value}));
或者,传播语法是一种制作对象的浅表副本的便捷方法:
setForm({
...form,
[e.target.name]: e.target.value
})
答案 1 :(得分:1)
尝试用
替换setForm(Object.assign(form, {[e.target.name]: e.target.value}));
setForm(prevState => ({
...prevstate,
[e.target.name]: e.target.value
}));