How i render checkboxes with nested array of objects

4.1k views Asked by At

I have a checkbox component which renders multiple day checkboxes. I need to print the values of the selected checkboxes. The sample given below looks like the one:

const [state, setState] = useState({ 
    "firstName": "",
    "lastName" : "",
    "mobileNumber" : "",
    "avalabilities": [{"availabilityId": "",

    day: [
      {
        value: "sun",
        name: "Sunday"
      },
      {
        value: "mon",
        name: "Monday"
      },
      {
        value: "tue",
        name: "Tuesday"
      },
      {
        value: "wed",
        name: "Wednesday"
      },
      {
        value: "thur",
        name: "Thursday"
      },
      {
        value: "fri",
        name: "Friday"
      },
      {
        value: "sat",
        name: "Saturday"
      }
    ],
    "isChecked": false,
    "checked" : false,
    "allChecked": false,
    "error": null});

this is the console value given below

{firstName: '', lastName: '', mobileNumber: '', avalabilities: Array(1), …}
allChecked: false
avalabilities: Array(1)
0:
availabilityId: ""
day: (7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
[[Prototype]]: Object
length: 1
[[Prototype]]: Array(0)
close: false
disabled: false
error: null
firstName: ""
isChecked: false
isPending: false
lastName: ""
mobileNumber: ""
open: false

this is how I am trying to render the arrays

{(avalabilities ||  [{}]).map((av, index) => {
    return (
      <div key={av.availabilityId}>


<>
            {av.day.map((item) => {
              return (
                <div>
                  <input
                    checked={item.checked || false}
                    onChange={() => handleChange3(item.value)}
                    type="checkbox"
                  />
                </div>
              );
            })}
          </>

But the error on mapping with day array is coming below like this

are not valid as a React child (found: object with keys {value, name}). If you meant to render a collection of children, use an array instead.

const checkedHandler = (event) => {
        
        setState(...)
        
        //Well, here I don't know how change the particular value of the 
     array...}

Any help is highly appreciated.

1

There are 1 answers

8
Nouman Rafique On BEST ANSWER

If i'm correct you want to show values of each checkbox and save the respective checkbox value when we toggle any checkbox. You have avalabilities array & in each object we have another day array. I render the all the avalabilities. Now when i toggle any checkbox, i pass three things to checkHandler:

  1. e which is native event of checkbox
  2. avIndex which is index of object in avalabilities array
  3. index which is index of object in day array.

Now each day object, i set a key checked and store the value of that checkbox by getting the value from e.target.checked.

Hope this solve your problem

newState.avalabilities[avIndex].day[index].checked = e.target.checked;
import { useState } from 'react';

export default function App() {
    const [state, setState] = useState({
        firstName: '',
        lastName: '',
        mobileNumber: '',
        avalabilities: [
            {
                availabilityId: '',
                day: [
                    { value: 'sun', name: 'Sunday' },
                    { value: 'mon', name: 'Monday' },
                    { value: 'tue', name: 'Tuesday' },
                    { value: 'wed', name: 'Wednesday' },
                    { value: 'thur', name: 'Thursday' },
                    { value: 'fri', name: 'Friday' },
                    { value: 'sat', name: 'Saturday' }
                ],
                isChecked: false,
                checked: false,
                allChecked: false,
                error: null
            }
        ]
    });

    const checkedHandler = (e, avIndex, index) => {
        console.log(e.target.checked, avIndex, index);
        setState((prev) => {
            let newState = { ...prev };
            newState.avalabilities[avIndex].day[index].checked = e.target.checked;
            return newState;
        });
    };

    return (
        <>
            {state.avalabilities.map((av, avIndex) => (
                <div key={av.availabilityId}>
                    {av.day.map((item, index) => (
                        <div key={index}>
                            <input
                                checked={item?.checked || false}
                                onChange={(e) => checkedHandler(e, avIndex, index)}
                                type='checkbox'
                            />
                            <span>{item.name}</span>
                        </div>
                    ))}
                </div>
            ))}
        </>
    );
}