0

I'm working on a recursive form based on a nested object, using React and MUI, and I'm to keeping track of the previous keys during the recursion.

At some point, as the user changes the form, I need to change the corresponding nested, state object.

So, I would need, in order to access the value in the form, some way of doing something similar to this:

const keyList = [k1, k2, ..., kn]

form[k1][k2]...[kn]

And, in the same vein, in order to set the value:

<TextField
  onChange={(e) => {
    const newForm = { ...form }

    newForm[k1][k2]...[kn] = newValue

    setForm(newForm)
  }}
/>

Is there a way of dealing with this? If so, how?

Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76
  • 1
    something similar to lodash get and set https://youmightnotneed.com/lodash#get https://youmightnotneed.com/lodash#set – cmgchess Apr 07 '23 at 17:39
  • :O I didn't know Lodash had something like that! – Philippe Fanaro Apr 07 '23 at 17:47
  • 1
    if you are using lodash already better go for it. its well tested – cmgchess Apr 07 '23 at 17:50
  • 1
    [This other SO answer](https://stackoverflow.com/a/52912542/4756173) really helped and did work for the most part, but I think I'm ditching it in favor of Lodash, all the more because they did some TypeScript sorcery that does in the work type-wise as well. – Philippe Fanaro Apr 07 '23 at 18:04

1 Answers1

1

I often use functions like these:

const getPath = ([p, ...ps]) => (o) =>
  p == undefined ? o : getPath (ps) (o && o[p])

const setPath = ([p, ...ps]) => (v) => (o) =>
  p == undefined ? v : Object .assign (
    Array .isArray (o) || Number .isInteger (p) ? [] : {},
    {...o, [p]: setPath (ps) (v) ((o || {}) [p])}
  )

Given const keyList = [k1, k2, ..., kn], with these functions

form[k1][k2]...[kn]

could be written

getPath (keyList) (form)

and

const newForm = { ...form }

newForm[k1][k2]...[kn] = newValue

setForm(newForm)

could be written

setForm (setPath (keyList) (newValue) (form))

Edit

An edit added this content:

As mentioned by @cmgchess, you could also use Lodash's get and set.

This is true, but there might be a concern about the API (since lodash's version starts with "path.to.node" rather than ["path", "to", "node"] as does the proposed alternative. Worse, from my perspective, is that set mutates its input. I'm not sure how that will work with your React environment, but I personally try to avoid that as much as possible. setPath above does not mutate the input, but avoids a complete deep clone by structurally sharing what it can of the input.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103