反应父级的并发集状态

  • 本文关键字:并发 状态 reactjs
  • 更新时间 :
  • 英文 :


假设您希望某个子组件在init(而不是在用户输入时(设置父组件的状态。在下面的示例中,如果有多个组件更改同一父级,则某些子级所做的更改将丢失!

对父级执行并发更改的正确方法是什么?

import { useEffect, useState } from 'react';

function Child({letter,parentState,setParentState}) {
const [value,setValue] = useState("hello");
useEffect(()=>{
const new_parent_state={
...parentState,
[letter]: "hello"
}
setParentState(new_parent_state);
},[value]);
return <div>hello {letter}</div>
}

function App() {
const [parentState,setParentState] = useState({"A": null, "B": null})
useEffect(()=>{
console.log(parentState);
});
return (
<div className="App">
<Child key="A" letter="A" parentState={parentState} setParentState={setParentState}></Child>
<Child key="B" letter="B" parentState={parentState} setParentState={setParentState}></Child>
</div>
);
}
export default App;

预期输出为

{
"A":"hello",
"B": "hello"
}

实际输出为

{
"A": null,
"B": "hello"
}

组件A:

parentState={"A": null, "B": null}。A将状态更新为:{"A": "hello", "B": null}

组件B:

parentState={"A": null, "B": null}。B将状态更新为:{"A": null, "B": "hello"}

如果交换DOM树中A和B组件的顺序,您将看到其他输出。

您看到的问题的原因是提供给单个组件的parentState已过时。您需要使用setter回调使其按预期工作(始终获得更新状态(。

代替:

const new_parent_state={
...parentState,
[letter]: "hello"
}
setParentState(new_parent_state);

用途:

setParentState((prevParentState) => ({
...prevParentState,
[letter]: "hello"
}));

工作演示:

function Child({ letter, parentState, setParentState }) {
const [value, setValue] = React.useState("hello");
React.useEffect(() => {
setParentState((prevParentState) => ({
...prevParentState,
[letter]: "hello"
}));
}, [value]);
return <div>hello {letter}</div>;
}
function App() {
const [parentState, setParentState] = React.useState({ A: null, B: null });
React.useEffect(() => {
console.log(parentState);
});
return (
<div className="App">
<Child
key="A"
letter="A"
parentState={parentState}
setParentState={setParentState}
></Child>
<Child
key="B"
letter="B"
parentState={parentState}
setParentState={setParentState}
></Child>
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

旁注:您可能期望在这里有三个日志。但React已经智能地将两个状态更新分批为一个更新。

最新更新