React `updateState`
Tags: react, state
Published: 2022-02-20 06:37:00

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 -

```javascript
import { useState } from 'react';

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

  return <>
    ...
  </>
}
```

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](https://reactjs.org/docs/fragments.html#short-syntax).

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 -

```javascript
import { useState } from 'react';

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

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 - 

```javascript
...

const onPageSizeChange = (newPageSize) => {
  setState((prevState) => {
    return {
      ...prevState,
      pageSize: newPageSize,
    }
  })
}
```

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` -

```javascript
...

const resetFilters = () => {
  setState((prevState) => {
    return {
      ...prevState,
      nameFilter: '',
      designationFilter: '',
    }
  })
}
```

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 -

```javascript
...

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

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

```

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.

```typescript
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];
};
```


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](https://reactjs.org/docs/state-and-lifecycle.html#state-updates-are-merged). 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.

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