Home > Back-end >  How to Slow Down React State Update Intentionally - Batch Updates
How to Slow Down React State Update Intentionally - Batch Updates

Time:03-17

Occasionally I may want to unmount and remount a component with new data inside it. This could look like:

setAllPosts(undefined);
setAllPosts(newArrayOfPosts);

Because React batches state changes, depending on where the newArrayOfPosts is coming from, the state won't change. I've been able to hack a solution with a setTimeout() of 1 second and then filling in setAllPosts(), but this feels so wrong.

Is there a best practice way to tell React to slow down for a moment? or maybe to not batch update this particular state change?

P.S. I know there are better ways to do this, but I am working inside a third party environment and am pretty limited to what I have access to.

CodePudding user response:

Once react 18 is available (it's currently a release-candidate) there will be a function that can force updates to not be batched: flushSync

import { flushSync } from 'react-dom';

flushSync(() => {
  setAllPosts(undefined);
});
flushSync(() => {
  setAllPosts(newArrayOfPosts);
});

Until then, you may need to do the setTimeout approach (though it doesn't need to be a whole second).

P.S. I know there are better ways to do this, but I am working inside a third party environment and am pretty limited to what I have access to.

Yeah, if you can do something else that would probably be better. Most of the time, if you want to deliberately unmount/remount a component, that is best achieved by using a key which you change when you want the remount to happen.

const [key, setKey] = useState(0);
const [allPosts, setAllPosts] = useState([]);

// ...
setKey(prev => prev   1);
setAllPosts(newArrayOfPosts);

// ...
return (
   <SomeComponent key={key} posts={allPosts} />
)

CodePudding user response:

Occasionally I may want to unmount and remount a component with new data inside it.

It sounds like this use-case calls for a useEffect() with a dependency based on something you care about, like another piece of state or prop being provided to this component.

useEffect(() => {
   setAllPosts(newArrayOfPosts);
}, [shouldUpdate]);

I've even seen examples of people triggered useEffect() with a dependency of a piece of state called count or renderCount. Not sure if this is necessarily best practice but it's one way to go about things.

const [count, setCount] = useState(0);
const [allPosts, setAllPosts] = useState([]);

useEffect(() => {
   setAllPosts(props.values);
}, [count]);

const handleChange = () => {
   setCount(prevCount => prevCount   1); // This will trigger your useEffect when handleChange() in invoked
}
  • Related