How can I store and update multiple values in React useState?
Asked Answered
W

5

42

I've a series of user data elements which I'm collecting inside a React component using hooks.

const [mobile, setMobile] = useState('');
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');

Each of these are updated as follows.

<input type="text"
       className="form-control"
       id="mobile"
       placeholder="Enter a valid mobile number"
       onChange={event => {setMobile(event.target.value)}}/>

Is there a more succint way to do this using an object as the variable?

Wamsley answered 19/1, 2020 at 20:3 Comment(3)
Sure, you could... use an object as the variable. const [values, setValues] = useState({ mobile: "", ... });.Gulledge
@Gulledge how do I call the set methods, inside the individual onChange events.Wamsley
setValues({ ...values, [prop]: newValue });?Gulledge
S
90

You should add name attributes to input tags. Each name must refer to key in AllValues object.

const [allValues, setAllValues] = useState({
   mobile: '',
   username: '',
   email: '',
   password: '',
   confirmPassword: ''
});
const changeHandler = e => {
   setAllValues({...allValues, [e.target.name]: e.target.value})
}
return (
   <input type="text"
       className="form-control"
       id="mobile"
       name="mobile"
       placeholder="Enter a valid mobile number"
       onChange={changeHandler}
   />
   // ...
)
Saltern answered 19/1, 2020 at 20:30 Comment(5)
I did not realize why [e.target.name] has to be inside []?Bogoch
This is the way to add object key by variable (e.target.name) name.Saltern
why should we use the name instead of the id? Convention only?Gibran
because ID has to be unique, but multiple elements can have same names.Saltern
TS7006: Parameter 'e' implicitly has an 'any' type.Delitescent
C
24

The above answer could create issues in some cases, the following should be the right approach.

const [allValues, setAllValues] = useState({
   mobile: '',
   username: '',
   email: '',
   password: '',
   confirmPassword: ''
});
const changeHandler = e => {
   setAllValues( prevValues => {
   return { ...prevValues,[e.target.name]: e.target.value}
}
}
Carcajou answered 7/1, 2021 at 8:56 Comment(2)
This should be safe more than the accepted answer. I have experienced some tricky bugs and this answer solved that problem.Librate
For React 16 and earlier, this might cause a problem because of Event Pooling. Be sure to use this only for React 17 or later. Note that you can still use this answer with some additional lines like <_name=e.target.name;_value=e.target.value> and using _name and _value instead of using e directly in the return phrase.Janus
C
7

Set initial values

const initialValues = {                   // type all the fields you need
name: '',
email: '',
password: ''
};

UseState

const [values, setValues] = useState(initialValues);       // set initial state

Handling the changes

const handleChange = (e) => {                
  setValues({
    ...values,                                // spreading the unchanged values
    [e.target.name]: e.target.value,          // changing the state of *changed value*
  });
};

Making the Form

<form>
  <input type="email"
   id="xyz"
   name="email"                                     // using name, value, onChange for applying changes
   value={email}
   onChange={changeHandler}
   placeholder="Enter your email"
   />
   // other inputs
</form>
Cumulonimbus answered 26/6, 2021 at 8:0 Comment(0)
O
0

to store multiple state in usestate for radio button in antd

 const [allValues, setAllValues ]= useState({
        validate:'',
        required:'',
        labelAlign:'',
        labelFontWeight:''
    })
    const changeHandler = (e, name) => {             
        setAllValues({
          ...allValues,                                
        [name]: e.target.value,          
        });
      };
     <Form.Item
            label="Validation"
            rules={[
              {
                required: true,
              },
            ]}
          >
          <Radio.Group
            onChange={(e) => changeHandler(e, "validate")}
            value={allValues.validate}
            style={{ paddingLeft: "15%" }}
          >
            <Radio value="True">True</Radio>
            <Radio value="False">False</Radio>
          </Radio.Group>
          </Form.Item>
Otes answered 14/5, 2024 at 12:43 Comment(0)
I
0

You may refer this (usestate with single object):

const [formData, setFormData] = useState({
    mobile: '',
    username: '',
    email: '',
    password: '',
    confirmPassword: ''
  });

  const handleChange = (event) => {
    // Update the state object with the new value
    setFormData({...formData, [event.target.name]: event.target.value });
  };
Imbue answered 14/5, 2024 at 18:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.