DEV Community

Cover image for No need to write change handlers for multiple React inputs!
Nick Scialli (he/him)
Nick Scialli (he/him)

Posted on

No need to write change handlers for multiple React inputs!

No need to write change handlers for multiple React inputs! You can create a function that takes both the prop name and the value as arguments. If using Typescript, use generics to narrow the type of the value based on the prop.

type User = {
  name: string;
  age: number;
  admin: boolean;
};

function App() {
  const [user, setUser] = useState<User>(defaultUser);

  const setUserProp = <P extends keyof User>(prop: P, value: User[P]) => {
    setUser({ ...user, [prop]: value });
  };

  return (
    <div>
      <input
        onChange={e => {
          setUserProp("name", e.target.value);
        }}
      ></input>
      <input
        onChange={e => {
          setUserProp("age", parseInt(e.target.value));
        }}
      ></input>
      <input
        onChange={() => {
          setUserProp("admin", !user.admin);
        }}
      ></input>
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Top comments (6)

Collapse
 
andomain profile image
Sam Anderson • Edited

I often further simplify this by giving the <input> elements a name property & then using the following

const changeHandler = (e) => {
   const {name, value} = e.currentTarget;
   setState({[name]: value});
}

...
<input name="name" onChange={changeHandler} />
<input name="age" onChange={changeHandler} />
...

Collapse
 
karataev profile image
Eugene Karataev

For the cases when you don't need current input state for validation, calculation, e.t.c you just can use uncontrolled inputs and read inputs' values via ref.

Collapse
 
nas5w profile image
Nick Scialli (he/him)

Awesome! I do think this will end up with type errors for varied types of object properties (e.g., numbers and booleans)

Collapse
 
andomain profile image
Sam Anderson

Of course, this was just a minimal example. When I use this properly in my Typescript projects I include typeguards etc. to ensure state types remain consistent.

Collapse
 
rosswilliams profile image
rosswilliams
const setUserProp = <P extends keyof User>(prop: P, value: User[P]) => ()

Nice use of generics here with keyOf, will use going forward.

Collapse
 
michaeljota profile image
Michael De Abreu

That's so simple, so useful. Thanks!