Home > front end >  React useState storing user input in an object
React useState storing user input in an object

Time:02-17

I'm trying to build a form using groups of radio inputs that save their values into a single state object.

The issue I'm having with the below code is the state is getting updated correctly, but the the radio checked attributes and the two paragraph tags are not re-rendering to show the new the text. If I re-render the component with some other method then the text updates to match the state.

I know in an ideal world I would have a useState() for each radio group, however the data that is used to generate the form is dynamic from a server so I can't predict what the shape of the state will look like and I need to send the input back as an object to the server. I've simplified my example but the issues is the same...

import { useState } from 'react'

const Form = () => {

    const [ data, setData ] = useState({});

    const handleChange = (key, value) => {
        data[key] = value
        setData(data)
    }

    return (
        <div>
            <h2>Form</h2>

            <p>Gender: { data.gender }</p>
            <p>Age: { data.age }</p>

            <form action="">
                <label>
                    Male
                    <input type="radio" name="gender" checked={data['gender'] === 'male'} onChange={() => handleChange('gender', 'male')} />
                </label>
                <label>
                    Female
                    <input type="radio" name="gender" checked={data['gender'] === 'female'}  onChange={() => handleChange('gender', 'female')} />
                </label>
                <label>
                    Old
                    <input type="radio" name="age" checked={data['age'] === 'old'}  onChange={() => handleChange('age', 'old')} />
                </label>
                <label>
                    Young
                    <input type="radio" name="age" checked={data['age'] === 'young'}  onChange={() => handleChange('age', 'young')} />
                </label>
            </form>
        </div>
    );
}

export default Form;

I'm still relatively new to react so any help would be much appreciated, I'm sure it's something fairly obvious that I'm missing!

CodePudding user response:

you are just updating the key in the data object and so the object itself will maintain its original reference. This won't cause a re-render since the actual state, the data object has not changed.

To get the component to render on state update, you can do setData({...data, [key]: value});

CodePudding user response:

I think I see the problem.

data[key] = value

Here, you're muting the state directly. Instead, try something like

const newData ={};
newData[key] = value;
setData(newData);

When you're doing setData your way, it looks and sees that data is already the same, and so does not update anything.

CodePudding user response:

const handleChange = (key, value) => {
        
        setData({...data, key : value})
    }

CodePudding user response:

Just Change This

const [ data, setData ] = useState({});

const handleChange = (key, value) => {
    setData({...data, [key]: value});
}
  • Related