我开始使用react钩子,我决定在useState
函数中放置一个对象而不是变量:
const [foo, setFoo] = useState({
term: '',
loading: false,
...
});
但是稍后我想更新它
const onChange = (e) => {
const { value } = e.target;
setFoo({ ...foo, term: value });
if(value) setFoo({ ...foo, loading: true });
...
}
...
return (
...
<input onChange={onChange} value={term} />
...
)
1。。为什么在第二个setFoo
中,当我检查foo
对象时,总是得到term
属性,其属性等于''
,就像初始值和输入是否不使用键入的字符更新?
-当我删除第二个setFoo
时,它起作用了,所以我想是因为setFoo
是异步的,但是如何解决此问题呢?
-我知道我们可以通过一次只致电setFoo
来解决此问题,但是我想知道其他解决方案吗?
2。。为什么这种问题在redux
中从未发生?
答案 0 :(得分:2)
解决方案:像这样使用一个setFoo
:
const onChange = (e) => {
const { value } = e.target;
setFoo({ term: value, loading: !!value });
...
}
!!
的意思是“转换为布尔值”。
答案 1 :(得分:1)
您可以通过使用所有新的键值对仅调用setFoo
来解决此问题,如下所示:
const onChange = (e) => {
const { value } = e.target;
const loading = value ? true : false;
setFoo({ ...state, term: value, loading });
....
}
更新:
要进行复杂的状态更新和对该部分进行更多控制,可以使用useReducer,并编写一个单独的reducer来更新状态。
答案 2 :(得分:1)
1。可能是因为您必须破坏foo
而不是state
setFoo({ ...foo, term: value });
2。。看看其他的挂钩,尤其是useReducer
如果您具有包含多个子值的复杂状态逻辑,或者下一个状态取决于上一个,则
useReducer
通常比useState
更可取。
您的代码可以变成:
const reducer = (state, action) {
switch(action.type) {
case 'loading':
return { ...state, loading: true };
case 'loaded':
default:
return { ...state, loading: false };
}
}
const initialState = {
term: '',
loading: false,
}
const [state, dispatch] = useReducer(reducer, initialState);
dispatch({
type: e.target.value ? 'loaded' : 'loading'
});