Search code examples
reactjsspread

State only getting the first letter from the input?


Hey I have an issue where I am collecting input from several inputs.. I tried to write a helper function for just updating the state object for each input, but it seems like the input is only gathering the first letter from my input and nothing else.. and it seems like it stores it once and then I can change it.. any idea what I'm missing her?

`

export const Form = ({addStudent}) => {
    const [newStudent, setNewStudent] = useState({school:"university"})
    const updateValue = e => {
        const { name, value } = e.target;
        setNewStudent({[name]: value, ...newStudent});
    }

    return (
        <section>
            <p>First Name</p>
                <input type="text" name="firstName"
                    onChange={updateValue}
                />
            <p>Last Name</p>
                <input type="text" name="lastName"
                    onChange={updateValue}
                />
            <label>Choose a school:</label>
                <select name="school"
                    onChange={updateValue}
                >
                    <option value="university">university</option>
                    <option value="highSchool">High School</option>
                </select>
            <button onClick={() => addStudent(newStudent)}>
                Add new Student
            </button>
        </section>
  )
}

`

I tried to make the updateValue function dynamic with the values like this and now it seems to not work anymore...


Solution

  • You are overwriting the current existing value with your spread.

    setNewStudent({[name]: value, ...newStudent});
                               // ^^^^^^^^^^ overwriting existing value
    

    After the first keystroke (onChange) the field gets created and the value of that field is just one letter (because if was empty before). And it stays in this state because the new value is consistently overwritten by the previous (first) value.

    Note: You should be also using a callback while setting the new state, just to make sure it's up-to-date when updating.

    setNewStudent((prev) => ({ ...prev, [name]: value }));