Brief But full information about useState hook

Archana Kumari
4 min readNov 8, 2021
useState React hook

useState is the very first hook in react everyone learns. And as it is the very first hook, I am going to keep this blog as brief as I can but more and more informative. So, that you will need no other blog to understand useState.

What are hooks?

  • They are special function
  • used inside a functional component only

What is useState?

  • It is a react hook
  • It lets you add React State to a functional component
  • If you are familiar with class components this.state , then you will find that useState does the same work. Means class component’s this.state = useState of the functional component.

Why do we use useState to add a state and not a normal variable in the functional component?

  • normal variables “disappear” when the function exits but state variables are preserved by React.

Now, let’s dig into the SYNTAX of useState

const [state, setState] = useState(initialValue)

If you are new to the hooks world and wondering what are the two things that useState returned my next question is going to clear your doubts.

What does useState return?

  • It returns an array of 2 elements
  • 1st element: It is the state variable you wanted to declare
  • 2nd element: It is the function to update the state variable (which is also known as dispatch )
  • We use array destructuring to get the values returned by useState

If by any chance you are thinking why useState returned an array and not an object, let’s answer this query too

  • compared to object array is easy to use and more flexible
  • If the method returned an object with a fixed set of properties, you wouldn’t be able to assign custom names in an easy way.
// Without using object destructuring
const messageState = useState( '' );
const message = messageState.state;
const setMessage = messageState;

// Using object destructuring
const { state: message, setState: setMessage } = useState( '' );
const { state: list, setState: setList } = useState( [] );
// With array
const [message, setMessage] = useState('');

Now, let’s talk about the right-hand side syntax of the syntax we saw above

const [state, setState] = useState(initialValue)

What values we can pass as an argument of useState i.e initialValue?

  • initialValue can be of any data type, number, string, boolean, array, dict, etc.
  • Even you can pass a function as an argument too, but that function will eventually compute the initial value.
Note - useState runs on every render/re-render, so it will compute initial value on every render but it will ignore it after first render as it is not needed anymore.

let’s learn about Lazy initialization here:

Remember that the only time React needs the initial state is initially. Meaning, it only really needs the initial state on the first render. But because our function body runs every time there’s a re-render of our component, we end up running that code on every render, even if its value is not used or needed.

For this we use Lazy initialization:

const getInitialState = () => Number(window.localStorage.getItem('name'))
const [name, setName] = React.useState(getInitialState)

So if you pass a function to useState, React will only call the function when it needs the initial value (which is when the component is initially rendered). So, lazy initialization is a performance optimization. But you should use this only when the initial value computations are expensive.

How to update the state?

You can simply update the state variable with the help of the second element you got as an output of the useState hook.

const Message = () => {
const [message, setMessage] = useState( '' );

return (
<div>
<input
type="text"
value={message}
placeholder="Enter a message"
onChange={e => setMessage(e.target.value)}
/>
<p>
<strong>{message}</strong>
</p>
</div>
);
};

The things you will have to keep in mind if you will be using an object as a state variable

  1. The importance of immutability: if you use the same value as the current state to update the state (React uses Object.is for comparing), React won’t trigger a re-render.

2. And the fact that the dispatch function returned by useState doesn’t merge objects like setState() does in class components

Common mistakes we do
const [classObj, setClass] = useState({ class: '' });
classObj.class = e.target.value;
setClass(classObj); //This will not work
const newClassObj = { class: e.target.value };
setClass(newClassObj); //This will work
OR
const val = e.target.value;
setClass(prevState => {
return { ...prevState, class: val } // This will work
});

Now, the last point of this blog. What is best practice: Multiple state variables or one state object?

const [id, setId] = useState(-1);
const [book, setBook] = useState('');
const [author, setAuthor] = useState('');
ORconst [bookObj, setBook] = useState({
id: 1,
book: '',
author: ''
});
  • When we use deeply nested objects, cloning deeply nested objects can be expensive because React may re-render parts of your applications that depend on fields that haven’t even changed.
  • the React documentation recommends splitting the state into multiple state variables based on which values tend to change together.

Thank you for reading!

Please leave comments if you have any suggestion(s) or would like to add point(s) or if you noticed any mistakes or typos or any queries!

P.S. If you found this article helpful, clap! 👏👏👏 [feels rewarding and gives the motivation to continue my writing].

--

--