使用嵌套 fields/object 时使用 React setState 钩子更新后状态消失
State disappears after update using React setState hook when using nested fields/object
在下面的示例中,当我更新某个字段时,状态对象中的另一个字段 disappears/unset 并且我收到有关输入变得不受控制的警告。示例如下:
const {useState} = React;
const App = () => {
const [user, setUser] = useState({
firstName: 'Mary',
lastName: 'Poppins',
});
return (
<div>
First Name: <input value={user.firstName} onChange={e => {
setUser({firstName: e.target.value});
}} />
<br />
Last Name: <input value={user.lastName} onChange={e => {
setUser({lastName: e.target.value});
}} />
<br />
{JSON.stringify(user, null, 2)}
</div>
);
};
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
如 React 文档所述:
However, unlike this.setState
in a class, updating a state variable always replaces it instead of merging it.
所以使用setUser
不会对对象进行浅合并,而是用整个对象替换状态,这会导致其他字段消失。在执行 setUser
.
时,您可以使用 Object.assign
或传播 (...
) 运算符将对象合并在一起
const {useState} = React;
const App = () => {
const [user, setUser] = useState({
firstName: 'Mary',
lastName: 'Poppins',
});
return (
<div>
First Name: <input value={user.firstName} onChange={e => {
setUser(Object.assign({}, user, {firstName: e.target.value}));
}} />
<br />
Last Name: <input value={user.lastName} onChange={e => {
setUser(Object.assign({}, user, {lastName: e.target.value}));
}} />
<br />
{JSON.stringify(user, null, 2)}
</div>
);
};
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
或者,创建一个名为 useMergeState
的自定义挂钩,以帮助您像通常那样自动合并 setState
。
在下面的示例中,当我更新某个字段时,状态对象中的另一个字段 disappears/unset 并且我收到有关输入变得不受控制的警告。示例如下:
const {useState} = React;
const App = () => {
const [user, setUser] = useState({
firstName: 'Mary',
lastName: 'Poppins',
});
return (
<div>
First Name: <input value={user.firstName} onChange={e => {
setUser({firstName: e.target.value});
}} />
<br />
Last Name: <input value={user.lastName} onChange={e => {
setUser({lastName: e.target.value});
}} />
<br />
{JSON.stringify(user, null, 2)}
</div>
);
};
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
如 React 文档所述:
However, unlike
this.setState
in a class, updating a state variable always replaces it instead of merging it.
所以使用setUser
不会对对象进行浅合并,而是用整个对象替换状态,这会导致其他字段消失。在执行 setUser
.
Object.assign
或传播 (...
) 运算符将对象合并在一起
const {useState} = React;
const App = () => {
const [user, setUser] = useState({
firstName: 'Mary',
lastName: 'Poppins',
});
return (
<div>
First Name: <input value={user.firstName} onChange={e => {
setUser(Object.assign({}, user, {firstName: e.target.value}));
}} />
<br />
Last Name: <input value={user.lastName} onChange={e => {
setUser(Object.assign({}, user, {lastName: e.target.value}));
}} />
<br />
{JSON.stringify(user, null, 2)}
</div>
);
};
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
或者,创建一个名为 useMergeState
的自定义挂钩,以帮助您像通常那样自动合并 setState
。