1

I am trying to change a deeply nested value within an object using a string path of the key to access the object.

Setup:

const [payload, setPayload] = useState({
    name: "test",
    download: true,
    downloadConfiguration: {
      product: {
        initialDownloadLength: 3,

      }}})

When object value is changed:

  const handleChange = (prop: any) => (e: React.ChangeEvent<HTMLInputElement>) => {

    if (typeof e.target.value === "number") {
      setPayload({ ...payload, [prop]: parseInt(e.target.value) });
    }

    if (typeof e.target.value === "string") {
      setPayload({ ...payload, [prop]: e.target.value });
    }
  };

When I change values in the outermost layer of the object it works fine and updates the value e.g.

onChange={handleChange("name")}

but I am unable to access the initialDownloadLength key that is nested within product and downloadConfiguration. I have tried "downloadConfiguration.product.initalDownloadLength" and using square brackets etc, but each time it creates a new object at the top most layer of the object.

mdbej
  • 103
  • 1
  • 10
  • Does this answer your question? [Accessing nested JavaScript objects and arrays by string path](https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-and-arrays-by-string-path) – pilchard Dec 07 '21 at 11:42
  • This doesnt seem to work for me unfortunately and rather just gets the value at that key, which I have no problem getting – mdbej Dec 07 '21 at 11:58
  • if you can get the value at the key you can set the value at the key... – pilchard Dec 07 '21 at 12:00
  • I can access the data using "downloadConfiguration.product.initalDownloadLength" normally, but in the case where I need the string value of the key in [prop], it doesnt work – mdbej Dec 07 '21 at 12:08

1 Answers1

1

You can use the solution in here dynamically-set-property-of-nested-object in your handleChange method like this:

// set method copied from the above link
function set(obj, path, value) {
    var schema = obj; 
    var pList = path.split('.');
    var len = pList.length;
    for(var i = 0; i < len-1; i++) {
        var elem = pList[i];
        if( !schema[elem] ) schema[elem] = {}
        schema = schema[elem];
    }
    schema[pList[len-1]] = value;
}
...

const handleChange = (prop) => (e) => {
  let value;
  if (typeof e.target.value === "number") {
    value = parseInt(e.target.value);
  }

  if (typeof e.target.value === "string") {
    value = e.target.value;
  }

  setPayload((prevState) => { 
     const newState = {...prevState};
     set(newState, prop, value);
     return newState;
 })
};
....

onChange={handleChange("downloadConfiguration.product.initialDownloadLength")}
Saeed Shamloo
  • 6,199
  • 1
  • 7
  • 18