简体   繁体   中英

onChange function for updating state with nested objects on form

I've got an form with different inputs that populates the next state defined like

const [userTaxData, setUserTaxData] = React.useState({
        businessName: "",
        rfc: "",
        address: {
            street: "",
            number: 0,
            suburb: "",
            city: "",
            state: "",
            country: "",
            zcode: 0
        }
    }); 

and the handleChange function defined like

const handleChange = (e) => {
        setUserTaxData({
            ...userTaxData,
            [e.target.name]: e.target.value
        });
    };

But the problema I've faced is that when I try to change the "zcode" property it is not working and it is because is inside the "address" object, so I need you support because I don't know how to access to "address" properties.

A simple way to do it is to test if you have update inside address property or not:

const handleChange = (e) => {
  
    if (Object.keys(userTaxData.address).includes(e.target.name)) {
      setUserTaxData({
        ...userTaxData,
        address: { ...userTaxData.address, [e.target.name]: e.target.value },
      });
    } else {
      setUserTaxData({
        ...userTaxData,
        [e.target.name]: e.target.value,
      });
    }
  };

You can't update nested object states with string keys, however if you flatten the object, you can.

Example:

 const flattenObject = (obj) => Object.assign({}, ... function _flatten(o) { return [].concat(...Object.keys(o).map(k => typeof o[k] === 'object'? _flatten(o[k]): ({ [k]: o[k] }))) }(obj)) const unflattenObject = (obj) => { var result = {} for (var i in data) { var keys = i.split('.') keys.reduce(function(r, e, j) { return r[e] || (r[e] = isNaN(Number(keys[j + 1]))? (keys.length - 1 == j? data[i]: {}): []) }, result) } return result } const handleChange = (e) => { const flattened = flattenObject(userTaxData) flattened[e.target.name] = e.target.value const unflattened = unflattenObject(flattened) setUserTaxData(unflattened); };

(Flattening code taken from this SO post, unflattening code taken from this SO post)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM