title: React Child Component not re-rendering when props change
body: <p>I'm trying to create a list of nested/grouped checkboxes, where selecting one of the checkbox (parent) should select other checkboxes (all its children) based on a array of data objects. Right now, hard coding the <code>checked</code> value in the <code>App.js</code> state reflects the checkbox output ticks, but when the state is being modified by  passing the <code>setState</code> as props to the child components, the checkboxes do not update. </p>
  
  <p>One hacky way of partially solving what I'm trying to do, is by using a <code>useState</code> in the <code>CheckBoxGroup.js</code> onChange methods, to change a boolean value, thus forcing the component to update. But even then, the console shows the correct changed props.state, but the app.js component state doesn't reflect. Without the useState, the checkboxes do not seem to re-render as well. Can someone help with this please? 
  Thanks</p>
  
  <p>The following is the code. 
  Code Sandbox link here: <a href="https://codesandbox.io/s/red-haze-ij1km?fontsize=14&amp;hidenavigation=1&amp;theme=dark" rel="nofollow noreferrer">https://codesandbox.io/s/red-haze-ij1km?fontsize=14&amp;hidenavigation=1&amp;theme=dark</a></p>
  
  <p><strong>App.js</strong></p>
  
  <pre><code>import React, { useState } from "react";
  import "./styles.css";
  import FoodGroup from "./FoodGroup";
  
  export default function App() {
    let arr = [
      {
        name: "Fruits",
        parentId: 100,
        data: [{ value: "Apple", id: 1 }, { value: "Banana", id: 2 }]
      },
      {
        name: "Vegetables",
        parentId: 200,
        data: [{ value: "Potato", id: 3 }, { value: "Onion", id: 4 }]
      }
    ];
    const [state, setState] = useState({
      // basically selecting all id : { selected : true } for parent id and child id
      1: { selected: false },
      2: { selected: false },
      100: { selected: false }
    });
  
    return (
      &lt;div className="App"&gt;
        &lt;FoodGroup data={arr} state={state} setState={setState} /&gt;
      &lt;/div&gt;
    );
  }
  </code></pre>
  
  <p><strong>FoodGroup.js</strong></p>
  
  <pre><code>import React from "react";
  import CheckBoxGroup from "./CheckBoxGroup";
  
  const FoodGroup = props =&gt; {
    let groups = props.data.map((group, index) =&gt; (
      &lt;CheckBoxGroup
        group={group}
        key={index}
        data={props.data}
        setState={props.setState}
        state={props.state}
      /&gt;
    ));
    return &lt;ul&gt;{groups}&lt;/ul&gt;;
  };
  
  export default FoodGroup;
  </code></pre>
  
  <p><strong>CheckBoxGroup.js</strong></p>
  
  <pre><code>import React, { useState } from "react";
  import CheckBox from "./CheckBox";
  
  const CheckBoxGroup = props =&gt; {
    // const [a, b] = useState(false);
    const onChildChange = (child, e) =&gt; {
      let childSelected = props.state;
      if (!childSelected[child]) {
        childSelected[child] = {};
      }
      childSelected[child].selected = e.target.checked;
      props.setState(childSelected);
      // b(!a); a hacky way I found a work around to force re render the component otherwise it doesn't
      // work
    };
  
    const onParentChange = (child, e) =&gt; {
      let childSelected = props.state;
      if (!childSelected[child]) {
        childSelected[child] = {};
      }
      let childInThatParent = [];
      props.data.forEach(group =&gt; {
        if (group.parentId === child) {
          group.data.forEach(item =&gt; {
            childInThatParent.push(item.id);
          });
        }
      });
      childSelected[child].selected = e.target.checked;
  
      childInThatParent.forEach(child =&gt; {
        if (!childSelected[child]) {
          childSelected[child] = {};
        }
        childSelected[child].selected = e.target.checked;
      });
  
      props.setState(childSelected);
      // b(!a);
    };
  
    let checkboxes = props.group.data.map((item, index) =&gt; (
      &lt;CheckBox
        onChange={onChildChange}
        value={item.value}
        id={item.id}
        key={item.id}
        setState={props.setState}
        state={props.state}
      /&gt;
    ));
  
    return (
      &lt;React.Fragment&gt;
        &lt;CheckBox
          onChange={onParentChange}
          value={props.group.name}
          id={props.group.parentId}
          countrySelected={props.state}
          setState={props.setState}
          state={props.state}
        /&gt;
        &lt;ul&gt;{checkboxes}&lt;/ul&gt;
      &lt;/React.Fragment&gt;
    );
  };
  
  export default CheckBoxGroup;
  </code></pre>
  
  <p><strong>CheckBox.js</strong></p>
  
  <pre><code>import React, { useState } from "react";
  
  const CheckBox = ({ state, id, onChange, value }) =&gt; {
    return (
      &lt;li&gt;
        &lt;input
          type="checkbox"
          value={id}
          onChange={e =&gt; {
            onChange(id, e);
          }}
          checked={state[id].selected}
        /&gt;
        {value}
      &lt;/li&gt;
    );
  };
  
  export default CheckBox;
  </code></pre>