SECRET OF CSS

Synchronous State in React Using Hooks | by Mohit Passan | Jun, 2022


A method to pass a callback function to setter functions of React hooks

1*QKk0Oi 2UqsD3Ji501 4gQ

The useState hook allows you to create a state inside a functional component which tells React to re-render whenever it is changed. It is different from using a normal variable because its value persists between rerenders and also causes the component to rerender when changed.

Here is the way to use the hook:

import { useState } from 'react';const Monkey = () => {
const [bananas, setBananas] = useState(0);
...
}

The hook has two parts: the argument, and its return value:

  • Argument: The argument provided is the initial value of the state.
  • Return value: It returns two things: the state variable and the function that is used to change the value of that variable.

To use the state, we simply use the variable inside the braces. {}

<div>
<p>I have eaten {bananas} bananas</p>
</div>

Setting state

There are two ways to set the stage given a value as an argument and a function as an argument.

  1. Value as argument
const eatMore = () => {
setBananas(bananas + 1);
};

2. Function as argument

const shitSome = () => {
setBananas((bananas) => bananas - 1);
};

React sets this state asynchronously, which means that the state is not changed immediately but after a few milliseconds. React sets its state asynchronously because doing otherwise can result in an expensive operation. Making it synchronous might leave the browser unresponsive.

Asynchronous setState calls are batched to provide a better user experience and performance.

A problem that arises is that if we access the state immediately after calling the setter function, we get the existing value and not the updated one.

const eatMore = () => {
setBananas(bananas + 1);
console.log(bananas);
}

Below you can see that the rendered value is different from the value that is logged in the console.

1*Ou5hZUGdCs2QE34XVidkUw

Class components

If you have used class components before, then you might know about the setState function.

It also does not return a Promise, so using async/await or anything similar will not work. When the state is actually set can vary. Usually, it happens on the next render, but it can sometimes be batched for performance.

The setState function takes an optional callback parameter that can be used to make updates after the state is changed.

eatMore = () => {
this.setState({ bananas: this.state.bananas + 1 }, () => {
console.log(this.state.bananas);
});
}

Here, we can see that it works:

Two buttons that add or subtraction bananas: eat some and shit some.

The solution that we saw above does not work for the setter function that was returned by the useState hook.

Even if you try to pass a callback function to the setter function, React gives you a warning and suggests you use the useEffect hook, but it is not the best solution for every use case.

Using functional argument

We know that the setter function also takes a function as an argument which takes the initial value and returns the modified value. What we can do is call our function inside this function and then return the required value.

const eatMore = () => {
setBananas(bananas => {
const modifiedValue = bananas + 1;
console.log(modifiedValue);
return modifiedValue;
});
};

Below you can see that the increment function works perfectly but the decrement function is problematic

1*du8g XIFB6vNp6Hp68P pg

The above solution is great, but we can abstract it to make the code look cleaner and to abstract the solution we will use custom React hooks.

Building your own hooks lets you extract component logic into reusable functions. A custom hook is a JavaScript function whose name starts with use and that may call other Hooks.

This hook will optionally take a callback function which gets called with the prevValue and the newValue. Here’s the code:

To use this, try this code:

Here’s an elegant solution:

1*Wah1oS1sqGFYZYtbMcIgHQ

App.js

useStateWithCallback.js



News Credit

%d bloggers like this: