reactjs挂钩中的连续状态对象设置问题

时间:2019-03-08 13:25:47

标签: javascript reactjs redux

我开始使用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中从未发生?

3 个答案:

答案 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 });

working useState example

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'
});

working useReducer example on CodeSandbox