Explain Codes LogoExplain Codes Logo

The useState set method is not reflecting a change immediately

javascript
react-hooks
state-management
use-effect
Alex KataevbyAlex KataevΒ·Jan 4, 2025
⚑TLDR

useState doesn't update instantly. It holds a party for all the changes and rollouts them out in the next render cycle (akin to launching all the changes together for a maximal impact). To act on updated state, you've got the power of useEffect:

const [value, setValue] = useState(initialValue); // 🚫 Remember, no party yet, so `value` won't reflect new state here setValue(newValue); // βœ… Boom! Party starts here: Use `useEffect` to run code after `value` updates useEffect(() => { // Code that needs the updated `value` }, [value]);

The VIP party guest is useRef if you need an immediate peek at the variable without causing a re-render:

const valueRef = useRef(initialValue); // Update ref valueRef.current = newValue; // βœ… The party is always happening here, access `valueRef.current` immediately

Why is useState playing hard to get?

The core of React is all about reconciliation and rendering. When you call useState, you're asking React to schedule a re-render. But instead of dropping everything to attend to this request, React efficiently batches them and addresses during the next cycle.

Much like you wouldn't wake up in the middle of the night to make a sandwich, React doesn't disrupt the natural flow for every single state update. The sandwich (render) tastes better in daylight (next cycle).

To keep track of state changes, useEffect rides to the rescue ensuring actions are completed after the state update.

Merging new updates with the previous ones? Use a callback in setValue:

setValue(prevValue => { // mix `prevValue` cocktail with `newValue` return newValue; });

Advancing from useState to useReducer

For more complex state logic, trade in your useState for a useReducer. It's like going from a bicycle to a motorbike.

const [state, dispatch] = useReducer(reducer, initialState);

Dealing with a bunch of state updates at once? What about fetch requests raining like cats and dogs? Punch back with Promise.all and catch them in your trusty umbrella, the useRef.

Implementing state updates: Strategies for the eager bees

The temporary outpost (tempValue):

let tempValue = 'temporary'; // This space is for rent! Update & access right away! tempValue = 'updated value';

The thoughtful useEffect:

useEffect(() => { // This is where magic happens! }, [value, otherDependency]); // These are your magic wands!

Break the closure curse:

const handleSomething = useCallback(() => { // Free of closure's curse! Use state & props directly }, [value, otherDependency]);

The domain of useReducer and useContext:

Replace prop drilling with useContext hook. It's like sending your state on a world tour!