DEV Community

Agnel Waghela
Agnel Waghela

Posted on

React `updateState`

I'm a newbie in React, and I'm working on a project for a Public Health Unit named 'Gully Clinic' using Material UI and Redux Toolkit.

I believe if you have worked on a React project then it wouldn't be soon enough to come across component state management. I think this one of those basics you learn when you begin learning React.

The syntax goes like this for a functional component -

import { useState } from 'react';

const CustomInput = (props) => {
  const [value, setValue] = useState('');

  return <>
    ...
  </>
}
Enter fullscreen mode Exit fullscreen mode

In case you are wondering what are those empty <></> brackets, they are the shorthand form for <React.Fragment></React.Fragment>. You can find more on this in the official docs.

This was a component which made use of a single state value.
In a real-world scenario, this is not the only case and there are multiple state values to be stored and handled.

For example, if you have a data grid whose pageSize needs to be managed via state along with values for various filters, all of which could be managed via a single state, say like this -

import { useState } from 'react';

const EmployeeDataGrid = (props) => {
  const [state, setState] = useState({
    pageSize: 5,
    nameFilter: '',
    designationFilter: '',
  });
}
Enter fullscreen mode Exit fullscreen mode

To update a state, for example when pageSize is changed via some user interaction, for a such a scenario the best practice is to set the state as shown below -

...

const onPageSizeChange = (newPageSize) => {
  setState((prevState) => {
    return {
      ...prevState,
      pageSize: newPageSize,
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

Here we are using the function argument variant of the setState method

Another scenario is wherein you need to update multiple state values together, say for example you provide the user to reset all the filters at once with a button interaction which you'd handle using an event listener like resetFilters -

...

const resetFilters = () => {
  setState((prevState) => {
    return {
      ...prevState,
      nameFilter: '',
      designationFilter: '',
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

If you notice, if there are many such interactions in your app which changes the state, then eventually you'll have many functions or event listeners with this piece of code setState((prevState) => { ... }) in them. For me, this became a problem because it began to reduce the readability of the code and the unnecessary increase in the component code size.

The updateState function along with setState

So, I wrote the updateState function in the component itself which would accept partial state key value pairs and update the state. Take a look -

...

const updateState = (newState) => {
  setState((prevState) => {
    return {
      ...prevState,
      ...newState
    }
  })
}

// usage
const resetFilters = () => {
  updateState({
    nameFilter: '',
    designationFilter: '',
  })
}

Enter fullscreen mode Exit fullscreen mode

Adding updateState to the components was repetitive because every stateful component needed updateState. So, I extracted out it to a separate individual utility function named useObjectState which return the updateState along with the usual state object and setState function.

import { useState } from 'react';

export const useObjectState = (initialState) => {
  const [state, setState] = useState(initialState);

  const updateState = (newState) => {
    setState((prevState) => {
      return {
        ...prevState,
        ...newState
      }
    });
  }

  return [state, setState, updateState];
};
Enter fullscreen mode Exit fullscreen mode

If you liked this post, may be found it useful in someway or have something to say just let me know in the comments. :)

Important Note

You may say updateState is not required as this is handled already by setState as stated in the official docs. If you've really worked with both the Class based components and functional components then you would notice that setState doesn't work with partial objects in functional components. The type definition of SetStateAction in the @types/react/index.d.ts confirms this. You'll find in this file the following around line 885.

// Unlike the class component setState, the updates are not allowed to be partial
type SetStateAction<S> = S | ((prevState: S) => S);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)