如何在Reactjs和Typescript中使用useEffect更新对象

时间:2020-05-31 03:27:23

标签: javascript reactjs typescript react-native react-redux

我是Reactjs + Typescript的新手,我想弄清楚为什么我收到以下错误消息。

React 16.9

const STEP_STATUS = {
  COMPLETED: "Completed",
  INCOMPLETE: "Incomplete",
};

const Foo = () => {
  const [state, setState] = useState({
    step: 1,
    firstName: '',
    lastName: '',
    status: STEP_STATUS["INCOMPLETE"],
  });

const nextStep = () => {
    setState({...state, step: state.step + 1});
  }

useEffect(() => {
    if (state.step + 1 !== state.step) {
      // setState(prev => {...prev, state.step = STEP_STATUS["COMPLETED"]}); // I tried this too
      setState(...state, state.status = STEP_STATUS["COMPLETED"]);
    } else {
      console.log("error");  // don't mind this line
    }
  }, [state]);

我尝试使用useEffect创建副作用,在按下按钮nextStep(将用户带到下一页)之后,我想更新在进入下一页之前,当前页面的状态为“已完成”。

我可能确实做错了。

任何帮助都会很有帮助。

当前错误

×
TypeError: state is not iterable
  53 | useEffect(() => {
  54 |   if (state.step + 1 !== state.step) {
  55 |     // setState(prev => {...prev, state.step = STEP_STATUS["COMPLETED"]});
> 56 |     setState(...state, state.status = STEP_STATUS["COMPLETED"]);
     | ^  57 |   } else {
  58 |     console.log("error");
  59 |   }

2 个答案:

答案 0 :(得分:1)

您需要在setState调用周围放置对象括号,如下所示:

setState({...state, status: STEP_STATUS["COMPLETED"]})

此外,建议使用传递给setState的prevState值进行更新,以防止clousers。

答案 1 :(得分:1)

我认为使用整个state作为useEffect钩子上的依赖项数组不是一个好主意。实际上,这将导致在state挂钩内更新useEffect时产生无限循环,将导致该循环被反复触发。

看看您要实现的目标,我相信state.step应该在依赖项数组上。此外,您在引用对象内的属性时使用了错误的语法。您应该使用冒号(=,而不是使用等于(:)。

useEffect(() => {
  setState({
    ...state,
    status: STEP_STATUS["COMPLETED"]
  });
}, [state.step]);

如果您尝试使用setState中的回调,则可以对此进行修改:

setState((prevState) => ({
  ...prevState,
  status: STEP_STATUS["COMPLETED"]
}));