2

The state of this form consists of three levels: A > B > C

A: [
            {
                name: "foo",
                ...
                B: [
                    {
                        name: "bar",
                        ...
                        C:[
                            {
                                name: "baz",
                                ...
                            },
                            {
                                name: "bat":,
                                ...
                            }
                        ]
                    },
               ]
            },
            ...
]

Basically, there needs to be an input field for each name attribute in three resources that are children of each other.

 <div className="subvariation-tree">
                {
                this.state.A.map( (a, aIdx) =>
                    <div key={aIdx}>
                        <input type="text"
                            value={this.state.A[aIdx].name}
                            onChange={this.handleInputChange} />
                            {
                            a.B.map( (b, bIdx)  =>
                                <div key={bIdx}>
                                    <input type="text"
                                        value={this.state.A[aIdx].B[bIdx].name}
                                        onChange={this.handleInputChange} />
                                        {
                                        b.C.map( (c, cIdx) =>
                                            <div key={cIdx} >
                                                <input type="text"
                                                    value={this.state.A[aIdx].B[bIdx].C[cIdx]}
                                                    onChange={this.handleInputChange} />
                                            </div>
                                        )
                                        }
                                    </div>
                                </div>
                            )
                            }
                        </div>
                    </div>
                )
                }
            </div>

Problem is, I guess it seems obvious but I'm not able to access aIdx for example within the loop for the C attribute.

Is there any way around this? Is this a ridiculous design? A ridiculous use case for React? I am struggling pretty badly with this idea. I think I could manage it in vanilla JavaScript but I am trying to learn React.

6
  • I'm trying better understand the question - Why you need an input field for the name attribute? Commented Mar 28, 2018 at 9:13
  • Thanks! So, these are 'variations' and 'subvariationcategories' and 'subvariations' that are used to create different 'versions' of products for an ecommerce mockup. So let's say the Product is a shirt, then the first level variation might be for color: [red, white, blue, etc.] and then those need subCategories, say Size, which then need variations of their own, say [s, m, l, xl, etc.] -- and I'm stopping it at 2 levels, but this seems like a pretty standard ecommerce feature so I need to represent it somehow. I'm very confused by it though T_T Commented Mar 28, 2018 at 9:23
  • The user of this 'product variation management dashboard' needs to be able to add different variations, essentially as many as they want/need. Commented Mar 28, 2018 at 9:25
  • 1
    Isn't this.state.A[aIdx].B[bIdx].name the same as b.name ? You are the same iteration in your A and B at that point. (same for a.name and c.name). Commented Mar 28, 2018 at 10:35
  • 1
    btw you should have access to the aIdx in the C loop. Are you sure the problem is not the missing .name at the end ? Commented Mar 28, 2018 at 10:40

2 Answers 2

1

You can simply write in like

<div className="subvariation-tree">
{
  this.state.A.map( (a, aIdx) => {
    return <div key={aIdx}>
            <input type="text" value={a.name} onChange={this.handleInputChange} />
             {
                a.B.map( (b, bIdx)  => {
                  return <div key={bIdx}>
                           <input type="text" value={b.name} onChange={this.handleInputChange} />
                           {
                              b.C.map( (c, cIdx) => {
                                return <div key={cIdx} >
                                         <input type="text" value={c.name} onChange={this.handleInputChange} />
                                        </div>
                              })
                            }
                          </div>
                })
               }
           </div>
  })
}
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

So the parameters of map will keep a reference to the original state? I would have thought that map makes a copy, so as you update b in the state, you would lose connection
Your this.state.A will be changed if anything inside it is changed whether it is B or C, whole object will be eligible for re rendering. React based on its diff mechanism will update the dom.
1

You should actually have access to the aIdx in the loop for the C.

If the problem is that it shows [object Object] in the input it is because you have ommited the .name for the C elements.

So instead of

value={this.state.A[aIdx].B[bIdx].C[cIdx]}

use

value={this.state.A[aIdx].B[bIdx].C[cIdx].name}

But as Sakshi Nagpal's answer mentions you could have used a.name, b.name and c.name directly since you have a local variable for the iterated object.

Here is a demo with both approaches: https://codesandbox.io/s/mz82r16o8p

2 Comments

The problem is the value isn't reflect changes to the state, making it an essentially useless form. Should it be working like this? Or is it essentially impossible to keep track of a multi-tiered, dynamic form in React?
Ack nvm, it was once again my own mistake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.