Published on

React Hooks and Currying to Easily Update Simple State

Authors

I have been using the React functional and hook approach to components for some time now and really prefer it. To get an idea how to convert an existing class as well as the advantages have a look at a previous post of mine here.

One thing that I find often becomes very boilerplaty with React is where you simply want to update a state variable when the user interacts with your UI. You basically end up with very similar functions like the below:

const onNameChange = (e) => {
    setName(e.target.value);
};

const onSurnameChange = (e) => {
    setSurname(e.target.value);
};

const onAgeChange = (e) => {
    setAge(e.target.value);
};

...
return (
<>
...
<label>Name: </label>
<input type="text" value={name} onChange={onNameChange} />

<label>Surname: </label>
<input type="text" value={surname} onChange={onSurnameChange} />

<label>Age: </label>
<input type="number" value={age} onChange={onAgeChange} />
...
</>
);

Luckily this is easily solved using a functional concept called function currying. First lets define the function that will handle general state changes:

const onStateChange = (stateSetter) => {
  return (e) => {
    stateSetter(e.target.value)
  }
}

Now lets refactor our code above to use this:

const onStateChange = stateSetter => {
    return e => {
        stateSetter(e.target.value);
    };
};
//we have deleted the previous on methods as we do not need them anymore
...
return (
<>
...
<label>Name: </label>
<input type="text" value={name} onChange={onStateChange(setName)} />

<label>Surname: </label>
<input type="text" value={surname} onChange={onStateChange(setSurname)} />

<label>Age: </label>
<input type="number" value={age} onChange={onStateChange(setAge)} />
...
</>

This works as:

  • it passes the setter we need as a parameter
  • the onStateChange function then returns a function that takes an event as a parameter as uses the provided setter against that event

This approach should only be used if we simply need to set the value with no additional logic.

If you find that you have to start adding complicated checks and if statements to the onStateChange to cater for some other change event then rather make a new function to handle that particular change.