0

I am trying to implement checkbox in react but I am facing a issue while checking and uncheck of checkbox.

I tried to implement onchange handler .

onChange={() => {
                    // first approch
                    //  i.checked = !i.checked;
                    // setObj({ ...i});

                    // second approach
                    setObj({ ...i, checked: !i.checked });
                    setTimeout(ab, 2000);
                  }}

so I used two approach

In First approach i changed the toggle the checked property and then create new reference which is working fine

 i.checked = !i.checked;
   setObj({ ...i});

In second approach I created a new object or reference with toggle of checked property but this is not working why

{ ...i, checked: !i.checked }

why my first and second approach is different ?

here is my code

https://codesandbox.io/s/lucid-fire-cxp9c?file=/src/child.js:362-666

import React from "react";
export default function Child({ data, ab }) {
  const [obj, setObj] = React.useState(null);

  return (
    <>
      {data &&
        data.map((i, idx) => {
          return (
            <ul key={idx}>
              <li>
                <input
                  type="checkbox"
                  checked={i.checked}
                  onChange={() => {
                    // first approch
                    //  i.checked = !i.checked;
                    // setObj({ ...i});

                    // second approach
                    setObj({ ...i, checked: !i.checked });
                    setTimeout(ab, 2000);
                  }}
                />
                {i.label}
              </li>
              {i.childrens && i.childrens.length > 0 ? (
                <Child data={i.childrens} ab={ab} />
              ) : null}
            </ul>
          );
        })}
    </>
  );
}

any suggestion ...!!?

1 Answer 1

1

Okay, so mixing the state and props makes it a little messy. I did some refactoring and added in a little recursion for the tree of nested values you're using. I added comments above the changes I made.

var data = [/* your array of data */]


// recursive function to find the value in the tree
const setChecked = (data, label) => {
  if (!data || data.length === 0) return [];
  // grab the first element
  const [current, ...rest] = data;

  // if it's found, plop the element back into place with
  // check changed and dump in the rest of the elements
  if (current.label === label) {
    return [
      {
        ...current,
        checked: !current.checked,
        childrens: current.childrens.map((child) => ({
          ...child,
          checked: !current.checked
        }))
      },
      ...rest
    ];
  }

  // re-slot the element and recursively move
  // through the remaining siblings
  return [
    {
      ...current,
      childrens:
        current.childrens.length > 0
          ? setChecked(current.childrens, label)
          : current.childrens
    },
    ...setChecked(rest, label)
  ];
};

export default function App() {
  const [state, setState] = React.useState(data1);

  const handleChange = (data) => {
    setState(setChecked(state, data.label));
  };

  const ab = () => {
    console.log(JSON.stringify(state));
  };

  return (
    <div className="App">
      <Child data={state} ab={ab} handleChange={handleChange} />
    </div>
  );
}

// added the onChange handler to lift the state to the parent
export default function Child({ data, ab, onChange }) {
  return (
    <>
      {data &&
        data.map((i, idx) => {
          return (
            <ul key={idx}>
              <li>
                <input
                  type="checkbox"
                  checked={i.checked}
                  onChange={() => {
                    onChange(i);
                    setTimeout(ab, 2000);
                  }}
                />
                {i.label}
              </li>
              {i.childrens && i.childrens.length > 0 ? (
                <Child data={i.childrens} ab={ab} onChange={onChange} />
              ) : null}
            </ul>
          );
        })}
    </>
  );
}
Sign up to request clarification or add additional context in comments.

10 Comments

I totally agree your point.but every senior developer said make reusable component correct ? and event handler should be in same component ...if we move handlers to parent.then there dependency of parent component with child component
it there any better design ?
in setChecked function you are not checking in parent childrens object..it is only checking one level
last one question if some gave this problem to you.which approach you will choose parent child (form child you send click handlers to parent). or you create separate component reusable component having click handlers also
@sorry actually i am beginner in react , that why I am asking what is better approch
|

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.