DEV Community

Jeet Bhalani
Jeet Bhalani

Posted on

A ReactJS Hook : useState()

Image description
useState is a Hook that enables state variables to be used in functional components. This function takes the initial state and returns a variable with the current state value and another function to update it.

In React, there are two type of components class based and functional based. Functional components are simple functions that accept parameters as component properties and return valid JSX:

function React(props) {
  return <div>{props.useState}</div>
}
// Or as an arrow function
const React = (props) =>  <div>{props.useState}</div>

Enter fullscreen mode Exit fullscreen mode

There are no state or lifecycle methods, as you can see.

React Hooks are the functions that add state variables to functional components. They usually begin with the keyword use.

How to use useState Hook in ReactJS? What does it do?

useState allows you to add state to function components, as previously indicated. When you use useState inside a function component, it creates a single piece of state for that component.

Whereas in a class, the state is always an object, Hooks' state can be any type. Each state item contains a single value, which can be an object, an array, a boolean, or any other kind you can think of.

So, when is it appropriate to utilize the useState Hook? It's particularly effective for the local component state, but larger projects may require the usage of additional state management methods.

Declaring{ useState }in your React App.

To use the UseState hook in your App simply type the following code:

import React, { useState } from 'react';
Enter fullscreen mode Exit fullscreen mode

The useState Hook allows you to declare only one state variable (of any type) at a time, like this:

import React, { useState } from 'react';

const React= () => {
   const message = useState( '' );
   const listOfMessage = useState( [] );
}
Enter fullscreen mode Exit fullscreen mode

useStatetakes the initial value of the state variable as an argument.

You can pass it directly, as shown in the previous example, or use a function to initialize the variable.

const Message= () => {
   const message = useState( () => helloWorld() );
}
Enter fullscreen mode Exit fullscreen mode

The initial value will only be assigned on the first render and if it's a function, it will only be called on the first render.

The initial parameter of the useState Hook will be ignored in subsequent renders (due to a change of state in the component or a parent component) and the current value will be obtained.

Because its argument is only used for the first time — not every time the property changes — using useState alone won't work.

However, unlike the previous examples, useState does not just return a variable.

It returns an array with the state variable as the first element and a function to update the variable's value as the second element.

Array destructuringis commonly used to simplify the code.

const React= () => {
   const [message, setMessage]= useState( '' );
}
Enter fullscreen mode Exit fullscreen mode

Updating the useState in React Hooks

The second element returned by useState is a function that updates the state variable with a new value.

Here's an example of how to update the state variable.

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

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

This update function, on the other hand, does not immediately update the value.

  The useState parameter will be ignored after re-rendering the component, and this function will return the most recent value or the new state values.

Using state varibales as an object: In useState() Hooks

If we add another property to the message object (id) like in the previous example:

const React = () => {
  const [messageObj, setMessage] = useState({ message: '', id: 1 });

  return (
    <div>
      <input
        type="text"
        value={messageObj.message}
        placeholder="Enter a message"
        onChange={e => {
          const newMessageObj = { message: e.target.value };
          setMessage(newMessageObj); 
        }}
      />
      <p>
        <strong>{messageObj.id} : {messageObj.message}</strong>
      </p>
  </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

And we only update themessageproperty like in the above example, React will replace the original state object:

{ message: '', id: 1 }
Enter fullscreen mode Exit fullscreen mode

With the object used in the onChange event, which only contains the message property:

{ message: 'message entered' } // id property is lost
Enter fullscreen mode Exit fullscreen mode

You may replicate the behavior of setState() by passing the object to be replaced as a function argument and using the object spread syntax:

onChange={e => {
  const val = e.target.value;
  setMessage(prevState => {
    return { ...prevState, message: val }
  });
}}
Enter fullscreen mode Exit fullscreen mode

The ...prevState part will get all of the properties of the object and the message: value part will overwrite the messageproperty.

You just have to be careful when applying the spreadsyntax to multidimensional arrays because it won’t work as you might expect.

This leads us to another thing to consider when working with objects as the state.

Updating state in React hooks: For Nested objects

In JavaScript, multidimensional arrays are arrays within arrays:

[
  ['value1','value2'],
  ['value3','value4']
]
Enter fullscreen mode Exit fullscreen mode

You could use them to centralize all of your state variables. However, it is preferable to use nested objects for this purpose:

{
  'row1' : {
    'key1' : 'value1',
    'key2' : 'value2'
  },
  'row2' : {
    'key3' : 'value3',
    'key4' : 'value4'
  }
}
Enter fullscreen mode Exit fullscreen mode

However, when working with multidimensional arrays and nested objects, the spread syntax and Object. assign will create a shallow copy rather than a deep copy.

When copying an array, the spreadsyntax essentially goes one level deep. As a result, as the following example shows, it may not be suited for copying multidimensional arrays. (The same is true for spread syntax and Object.assign().)

let a = [[1], [2], [3]];
let b = [...a];

b.shift().shift(); //  1
//  Array 'a' is affected as well: [[], [2], [3]]
Enter fullscreen mode Exit fullscreen mode

but the important point is that when using nested objects, we can’t just use the spread syntax to update the state object.

For example, consider the following state object:

const [msgObj, setMsg] = useState({
  author: '',
  msg: {
    id: 1,
    text: ''
  }
});
Enter fullscreen mode Exit fullscreen mode

The following code snippets show some incorrect ways to update the text field:

// Wrong
setMsg(prevState => ({
  ...prevState,
  text: 'My message'
}));

// Wrong
setMsg(prevState => ({
  ...prevState.msg,
  text: 'My message'
}));

// Wrong
setMsg(prevState => ({
  ...prevState,
  msg: {
    text: 'My message'
  }
}));
Enter fullscreen mode Exit fullscreen mode

To properly update the text field, we have to copy to a new object the entire set of fields/nested objects of the original object

// Correct
setMsg(prevState => ({
  ...prevState,      
  msg: {             
    ...prevState.msg, 
    text: 'My message'    
  }
}));
Enter fullscreen mode Exit fullscreen mode

In the same way, here’s how you’d update the author field of the state object:

// Correct
setMsg(prevState => ({
  author: 'Joe',      
  ...prevState.msg  
}));
Enter fullscreen mode Exit fullscreen mode

Assuming the message object doesn’t change. If it does change, you’d have to update the object this way:

// Correct
setMsg(prevState => ({
  author: 'Joe',         
  msg: {              
    ...prevState.msg, 
    text: 'My message'    
  }
}));
Enter fullscreen mode Exit fullscreen mode

Conculsion

useState is a Hook (function) that enables state variables to be used in functional components. This function takes the initial state and returns a variable with the current state value (not necessarily the starting state) and another function to update it.

Top comments (0)