【问题标题】:React update state synchronously同步响应更新状态
【发布时间】:2021-03-21 19:20:32
【问题描述】:

我有一个 Master 组件,其中包含多个 Child 组件。子状态保存在 Master 中。孩子获得的第一个状态是,FORM_LOADED。然后我的 Master 组件中有以下代码。

const Master = (props) => {
  const [formStates, setFormStates] = useState()

  useEffect(() => {
    setFormStates({...formStates, Master: "FORM_LOADED"})
  },[])

  render (
    <>
      <Child view="Model1" formStates={formStates} setFormStates={setFormStates} />
      <Child view="Model2" formStates={formStates} setFormStates={setFormStates} />
      <pre>{JSON.stringify(formStates, undefined, 4)}</pre>
    </>
  )
}

const Child = (props) => {
  useEffect(() => {
    props.setFormStates({...props.formStates, [props.view]: "FORM_LOADED"})
  }, [])
  render (
    <p>{props.view}</p>
  )
}

我的问题是状态变量formStates 总是得到:

{
  Master: "FORM_LOADED",
  Model2: "FORM_LOADED"
}

Model1 不会出现在formStates 中。如果我添加更多子组件,则只有最后一个组件会反映在formStates 中。如何将 Model1 发送到 formStates

【问题讨论】:

    标签: reactjs use-state


    【解决方案1】:

    我不确定是否理解所有内容,但在 setState() 方法中,您可以获得旧值。 你可以这样做:

      useEffect(() => {
        props.setFormStates((oldVal) =>({...oldVal, ...props.formStates, [props.view]: "FORM_LOADED" }));
      });
      return <p>{props.view}</p>;
    };```
    

    【讨论】:

    【解决方案2】:

    问题可能是您每次都用新对象覆盖旧对象。试试:

    const Child = (props) => {
      useEffect(() => {
        props.setFormStates(prevFormStates => ({...prevFormStates, [props.view]: "FORM_LOADED"}))
      }, [])
      render (
        <p>{props.view}</p>
      )
    }
    

    【讨论】:

    【解决方案3】:

    您好,您定义的方法永远不会起作用,因为您正在将父级的状态设置在父级正在渲染其所有子级的流程中间。

    我认为您正在尝试检查您的所有孩子是否都已渲染。

    React 在调用父组件上的 componentDidMount 之前等待挂载所有子组件

    我认为这可以帮助你

    【讨论】:

    • 我正在使用功能组件(对不起,我在上面的问题中没有提到它)并且我在其他答案(使用以前的状态)之后得到了解决
    【解决方案4】:

    来自每个 useEffect 钩子的所有代码都在相同的重新渲染之前执行。这就是 React 的工作原理。所以他们每个人都使用formStates的旧状态。

    您可以使用以下代码来使用formState 的当前状态:

    const Master = (props) => {
      const [formStates, setFormStates] = useState()
    
      useEffect(() => {
        setFormStates((prev) => ({...prev, Master: "FORM_LOADED"}))
      },[])
    
      render (
        <>
          <Child view="Model1" formStates={formStates} setFormStates={setFormStates} />
          <Child view="Model2" formStates={formStates} setFormStates={setFormStates} />
          <pre>{JSON.stringify(formStates, undefined, 4)}</pre>
        </>
      )
    }
    
    const Child = (props) => {
      useEffect(() => {
        props.setFormStates((prev) => ({...prev, [props.view]: "FORM_LOADED"}))
      }, [])
      render (
        <p>{props.view}</p>
      )
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 2021-04-12
    • 2021-06-02
    • 2017-07-15
    • 2021-05-01
    • 2019-08-13
    • 2020-04-21
    相关资源
    最近更新 更多