Javascript 当道具更改时,反应子组件不重新渲染

Javascript 当道具更改时,反应子组件不重新渲染,javascript,html,css,reactjs,Javascript,Html,Css,Reactjs,我试图创建一个嵌套/分组复选框列表,其中选择一个复选框父项应根据数据对象数组选择其他复选框及其所有子项。现在,对App.js状态中的选中值进行硬编码反映了复选框输出标记,但是当通过将setState作为道具传递给子组件来修改状态时,复选框不会更新 部分解决我要做的事情的一种方法是,在CheckBoxGroup.js onChange方法中使用useState来更改布尔值,从而强制组件更新。但即使如此,控制台也会显示正确的已更改的props.state,但app.js组件状态不会反映。如果没有us

我试图创建一个嵌套/分组复选框列表,其中选择一个复选框父项应根据数据对象数组选择其他复选框及其所有子项。现在,对App.js状态中的选中值进行硬编码反映了复选框输出标记,但是当通过将setState作为道具传递给子组件来修改状态时,复选框不会更新

部分解决我要做的事情的一种方法是,在CheckBoxGroup.js onChange方法中使用useState来更改布尔值,从而强制组件更新。但即使如此,控制台也会显示正确的已更改的props.state,但app.js组件状态不会反映。如果没有useState,复选框似乎也不会重新渲染。有人能帮忙吗? 谢谢

下面是代码。 代码沙盒链接:

App.js

FoodGroup.js

CheckBoxGroup.js

CheckBox.js


在onChildChange和onParentChange方法中更新状态时,引用的是相同的状态。您可以检查沙盒以获得修复:


CheckBoxGroup.js文件中的Check onChildChange和onParentChange方法

@RezaGhorbani I在CheckBoxGroup.js中直接引用了状态,例如第7行。我使用的是let childSelected=props.state;而不是让childSelected={…props.state};
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 (
    <div className="App">
      <FoodGroup data={arr} state={state} setState={setState} />
    </div>
  );
}
import React from "react";
import CheckBoxGroup from "./CheckBoxGroup";

const FoodGroup = props => {
  let groups = props.data.map((group, index) => (
    <CheckBoxGroup
      group={group}
      key={index}
      data={props.data}
      setState={props.setState}
      state={props.state}
    />
  ));
  return <ul>{groups}</ul>;
};

export default FoodGroup;
import React, { useState } from "react";
import CheckBox from "./CheckBox";

const CheckBoxGroup = props => {
  // const [a, b] = useState(false);
  const onChildChange = (child, e) => {
    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) => {
    let childSelected = props.state;
    if (!childSelected[child]) {
      childSelected[child] = {};
    }
    let childInThatParent = [];
    props.data.forEach(group => {
      if (group.parentId === child) {
        group.data.forEach(item => {
          childInThatParent.push(item.id);
        });
      }
    });
    childSelected[child].selected = e.target.checked;

    childInThatParent.forEach(child => {
      if (!childSelected[child]) {
        childSelected[child] = {};
      }
      childSelected[child].selected = e.target.checked;
    });

    props.setState(childSelected);
    // b(!a);
  };

  let checkboxes = props.group.data.map((item, index) => (
    <CheckBox
      onChange={onChildChange}
      value={item.value}
      id={item.id}
      key={item.id}
      setState={props.setState}
      state={props.state}
    />
  ));

  return (
    <React.Fragment>
      <CheckBox
        onChange={onParentChange}
        value={props.group.name}
        id={props.group.parentId}
        countrySelected={props.state}
        setState={props.setState}
        state={props.state}
      />
      <ul>{checkboxes}</ul>
    </React.Fragment>
  );
};

export default CheckBoxGroup;
import React, { useState } from "react";

const CheckBox = ({ state, id, onChange, value }) => {
  return (
    <li>
      <input
        type="checkbox"
        value={id}
        onChange={e => {
          onChange(id, e);
        }}
        checked={state[id].selected}
      />
      {value}
    </li>
  );
};

export default CheckBox;