同步响应更新状态

React update state synchronously

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

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 中。如果我添加更多 child 个组件,只有最后一个组件反映在 formStates 中。如何让 Model1 进入 formStates

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

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

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

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

您好,您定义的方法永远行不通,因为您正在流程中间设置 parent 的状态,其中 parent 正在渲染其所有 child.

我认为您正在尝试检查您的所有 child 是否已呈现。

React 在 parent

上调用 componentDidMount 之前等待挂载所有 child 组件

我想这对你有帮助

每个 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>
  )
}