关于丹·阿布拉莫夫(Dan Abramov)在此处的回答,我发现了以下内容:
Does React keep the order for state updates?
当前(第16和更早的版本),默认情况下仅批处理React事件处理程序中的更新。有一个不稳定的API可以在极少数情况下在需要时强制在事件处理程序之外进行批处理。< / p>
他还在Github问题中提到了这一点:
https://github.com/facebook/react/issues/10231#issuecomment-316644950
在当前版本中,如果您在React事件处理程序中,它们将被一起批处理。 React将在React事件处理程序中完成的所有setState进行批处理,并在退出自己的浏览器事件处理程序之前应用它们
但是事实是,该摘要似乎证明,其中对setState
中的多个useEffect()
调用进行了更新。
问题
React是否也总是为setState()
中的多个useEffect
调用批量更新吗?还能在哪里做?
注意:根据他的回答,在下一个主要版本(可能是v17)上,默认情况下,React将在所有地方进行批处理。
SNIPPET:在useEffect()
内通过多个setState()
调用批量更新
function App() {
console.log('Rendering app...');
const [myState,setMyState] = React.useState(0);
const [booleanState, setBooleanState] = React.useState(false);
console.log('myState: ' + myState);
console.log('booleanState: ' + booleanState);
React.useEffect(()=>{
console.log('Inside useEffect...');
setMyState(1);
setMyState((prevState) => prevState +1);
setMyState(3);
setMyState(4);
setMyState(5);
setBooleanState(true);
},[]);
return(
<div>App - Check out my console!</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
答案 0 :(得分:6)
好问题。这是完成@FranklinOcean答案的其他信息。
当前版本的React答案,即16.8.3。
基于on the following codesandbox:
批量setStuff
通话:
useEffect
块中同步onClick={handlerFunction}
)未批量调用,每次都会触发重新渲染:
我将尝试使用React的未来版本重新运行沙箱,以了解其运行情况!
答案 1 :(得分:1)
如果状态更新直接发生,React将批处理您的更新。
批量:
export default () => {
const [a, setA] = React.useState(0);
const [b, setB] = React.useState(0);
useEffect(() => {
setA(1); setB(1);
},[]);
return (
<div>
<p>A: {a}</p>
<p>B: {b}</p>
</div> );
};
单击此按钮将只重新渲染一次组件。
非批量:
export default () => {
const [a, setA] = React.useState(0);
const [b, setB] = React.useState(0);
useEffect(() => {
setTimeout(() => { setA(1); setB(1); }, 1000); }
, []);
return (
<div>
<p>A: {a}</p>
<p>B: {b}</p>
</div> );
};
答案 2 :(得分:0)
只是想加入一个对我有用的“黑客”
@app.post("video/{video_id}")
async def do_something():
# do something
save_to_db(video_id)
另一种方法是编写一个“Reac.useEffect const [dishes, dishesSet] = React.useState(state)
const [isConnectedToDB, isConnectedToDBSet] = React.useState(false)
React.useEffect(() => {
const databaseDishesRef = firebase.database().ref(process.env.FIREBASE_DISHES_REF)
databaseDishesRef.on('value', (snapshot) => {
const value = snapshot.val()
// isConnectedToDBSet(true) // this was not working
dishesSet(() => {
isConnectedToDBSet(true) // had to move it in here to batch the state updates
return Object.entries(value).map(([, dish]) => dish)
})
})
return () => {
databaseDishesRef.off('value')
}
}, [])
isConnectedToDB”,然后在每次菜品更新时触发它..