10

I am trying to use react hook form to create nested arrays. I have attached a sandbox with my sample code

Code Snippet

<ul>
        {fields.map((item, index) => {
          return (
            <li key={item.id}>
              <label> single input </label>
              <input
                name={`test[${index}].task`}
                ref={register()}
                defaultValue={item.task}
              />
              <br />
              <label> first Name </label>
              <input
                name={`test[${index}].name.first`}
                ref={register()}
                defaultValue={item.name.first}
              />
              <br />
              <label>last Name </label>
              <input
                name={`test[${index}].name.last`}
                ref={register()}
                defaultValue={item.name.last}
              />
              <br />

              <label>First Nested </label>
              <input
                name={`test[${index}].nestedArray[${index}].firstNested`}
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />

              <br />
              <label> Second Nested </label>
              <input
                name={`test[${index}].nestedArray[${index}].secondNested`}
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />
              <br />

              <button type="button" onClick={() => remove(index)}>
                Delete
              </button>
            </li>
          );
        })}
      </ul>

Issue

The initial step works fine. I am able to get the data in the "nestedArray". but when I append for more than one nested array my data. My "nestedArray" always starts with a "null" the "null" continues to add if I append for more. How can I avoid this "null" value? I do not want to retain previous input. I want to avoid the null value completely.

Sample output

{
   "test":[
      {
         "task":"single",
         "name":{
            "first":"Jack",
            "last":"Box"
         },
         "nestedArray":[
            {
               "firstNested":"firstNested",
               "secondNested":"firstSecondNested"
            }
         ]
      },
      {
         "task":"Second",
         "name":{
            "first":"Kate",
            "last":"Smith"
         },
         "nestedArray":[
            **null,**
            {
               "firstNested":"SecondNested",
               "secondNested":"SecondNestedSecond"
            }
         ]
      }
   ]
}

Expected Sample output

{
   "test":[
      {
         "task":"single",
         "name":{
            "first":"Jack",
            "last":"Box"
         },
         "nestedArray":[
            {
               "firstNested":"firstNested",
               "secondNested":"firstSecondNested"
            }
         ]
      },
      {
         "task":"Second",
         "name":{
            "first":"Kate",
            "last":"Smith"
         },
         "nestedArray":[
            {
               "firstNested":"SecondNested",
               "secondNested":"SecondNestedSecond"
            }
         ]
      }
   ]
}

Steps to reproduce in Sandbox

  1. click on append
  2. provide details
  3. See data in console
  4. Click on append(again) to add another set of data
  5. Console will show "null" inside the nestedArray.

References

Code Sandbox

Code Snippet

<ul>
        {fields.map((item, index) => {
          return (
            <li key={item.id}>
              <label> single input </label>
              <input
                name={`test[${index}].task`}
                ref={register()}
                defaultValue={item.task}
              />
              <br />
              <label> first Name </label>
              <input
                name={`test[${index}].name.first`}
                ref={register()}
                defaultValue={item.name.first}
              />
              <br />
              <label>last Name </label>
              <input
                name={`test[${index}].name.last`}
                ref={register()}
                defaultValue={item.name.last}
              />
              <br />

              <label>First Nested </label>
              <input
                name={`test[${index}].nestedArray[${index}].firstNested`}
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />

              <br />
              <label> Second Nested </label>
              <input
                name={`test[${index}].nestedArray[${index}].secondNested`}
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />
              <br />

              <button type="button" onClick={() => remove(index)}>
                Delete
              </button>
            </li>
          );
        })}
      </ul>

2 Answers 2

3

How about this, does this work, it keeps the array brackets and doesnt have the null.

Maybe since the map index increases, the nestedArray filters for the value that is in the current map index but since it hasn't gone to the next index it creates a null for that iteration.

Code: https://codesandbox.io/s/react-hook-form-usefieldarray-nested-arrays-forked-9sxrt?file=/src/fieldArray.js:302-1778

      <ul>
        {fields.map((item, index) => {
          return (
            <li key={item.id}>
              <label> single input </label>
              <input
                name={`test[${index}].task`}
                ref={register()}
                defaultValue={item.task}
              />
              <br />
              <label> first Name </label>
              <input
                name={`test[${index}].name.first`}
                ref={register()}
                defaultValue={item.name.first}
              />
              <br />
              <label>last Name </label>
              <input
                name={`test[${index}].name.last`}
                ref={register()}
                defaultValue={item.name.last}
              />
              <br />

              <label>First Nested </label>
              <input
                name={`test[${index}].nestedArray[0].firstNested`} //changed index to 0
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />

              <br />
              <label> Second Nested </label>
              <input
                name={`test[${index}].nestedArray[0].secondNested`} //changed index to 0
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />
              <br />

              <button type="button" onClick={() => remove(index)}>
                Delete
              </button>
            </li>
          );
        })}
      </ul>

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

1 Comment

Seems like the code to your solution is in the sandbox, but the Sandbox has been deleted. Please consider keeping Sandboxes around that relate to SO questions. Particularly if they include the solution. Thanks.
1

Let me know if this works. Maybe you didnt need to index the nestedArray since its been mapped. It worked in the console for me without the null. I think since you already targetted "test" with:

`test[${index}].nestedArray.firstNested`

you might not need to index the nestedArray also?

      <ul>
        {fields.map((item, index) => {
          return (
            <li key={item.id}>
              <label> single input </label>
              <input
                name={`test[${index}].task`}
                ref={register()}
                defaultValue={item.task}
              />
              <br />
              <label> first Name </label>
              <input
                name={`test[${index}].name.first`}
                ref={register()}
                defaultValue={item.name.first}
              />
              <br />
              <label>last Name </label>
              <input
                name={`test[${index}].name.last`}
                ref={register()}
                defaultValue={item.name.last}
              />
              <br />

              <label>First Nested </label>
              <input
                name={`test[${index}].nestedArray.firstNested`} //removed index
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />

              <br />
              <label> Second Nested </label>
              <input
                name={`test[${index}].nestedArray.secondNested`} //removed index
                ref={register()}
                // defaultValue={item.nestedArray.nested}
              />
              <br />

              <button type="button" onClick={() => remove(index)}>
                Delete
              </button>
            </li>
          );
        })}
      </ul>

4 Comments

I think i got it to work here: codesandbox.io/s/…
Appreciate it! This simple misstep had me stuck for hours!
@Jesse I actually got lucky, i didn't even really look at your code lol
Actually this didn't work for me. I need the second ${[index]} to make that to an array. without it the json would not have the brackets.

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.