Bill
Bill

Reputation: 5150

React TypeScript 16.8 How to set state from a form input

When the component loads the default state is shown in the name and age inputs which is great but I want to be able to type in the form fields for name and age, at the moment I can't, if I could I expect the values from the name and age inputs to be updated to the state. Likewise when I press the button. Lastly I feel a should be setting a type definition for the state.

I can't understand how to get the values out of the form inputs and save them to state. I dont want to use a placeholder as the value is removed as the user starts to type. Im unsure how to set a type definition for the state.

import React, {useState} from 'react';

const State: React.FC = () => {

  type StateTypes = {
    name: string,
    age: number
  }

  const [state, setState] = useState({
    name: 'Bill',
    age: 23,
  });

  const changeState = () => {
    setState({ 
      ...state, 
      name: 'Jim', 
      age: 25,
    })
  }

  return (
    <div className="home-grid">
      <div>
        <p>Name: {state.name}</p>
        <p>Age: {state.age}</p>
        <hr/>
        <input type="text" value={state.name} onChange={changeState} /><br/>
        <input type="number" value={state.age} onChange={changeState}/><br/>
        <button onClick = {changeState}>Update State</button>
      </div>
    </div>
  );
}

export default State;

Upvotes: 1

Views: 7169

Answers (2)

Shubhanu Sharma
Shubhanu Sharma

Reputation: 2132

You can change state on change of input or you can create refs of component and get values on click of button. but as per react docs https://reactjs.org/docs/hooks-reference.html#usestate better you can keep your state as flat as possible by using multiple useState because in hooks react is not responsible for any mutation and if you still want to keep nested state then you can use useReducer hook.

here i've just done something just let me know any changes required.

const State = () => {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0);

  const changeName = ({target}) => {
    setName(target.value)
  }

  const changeAge = ({target}) => {
    setAge(target.value)
  }

  const submitForm = () => console.log({name, age})

  return (
    <div className="home-grid">
      <div>
        <p>Name: {name}</p>
        <p>Age: {age}</p>
        <hr/>
        <input type="text" value={name} onChange={changeName} /><br/>
        <input type="number" value={age} onChange={changeAge}/><br/>
        <button onClick = {submitForm}>Update State</button>
      </div>
    </div>
  );
}

Upvotes: 1

Clarity
Clarity

Reputation: 10873

You can do this:

const changeState = (e) => {
    const {value, name} = e.target; 
    setState({ 
      ...state, 
      [name]: value
    })
  }

For that to work your inputs need to have a name prop with the name of the field: <input name="name" ... />

Upvotes: 2

Related Questions