【问题标题】:React Child Component not re-rendering when props change道具更改时反应子组件不会重新渲染
【发布时间】:2020-05-01 21:39:36
【问题描述】:

我正在尝试创建一个嵌套/分组复选框列表,其中选择一个复选框(父级)应该基于一组数据对象选择其他复选框(其所有子级)。现在,在App.js 状态中硬编码checked 值反映了复选框输出的滴答声,但是当通过将setState 作为道具传递给子组件来修改状态时,复选框不会更新。

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

以下是代码。 代码沙箱链接在这里:https://codesandbox.io/s/red-haze-ij1km?fontsize=14&hidenavigation=1&theme=dark

App.js

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>
  );
}

FoodGroup.js

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;

CheckBoxGroup.js

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;

CheckBox.js

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;

【问题讨论】:

    标签: javascript html css reactjs


    【解决方案1】:

    当您在onChildChangeonParentChange 方法中更新状态时,您引用的是相同的状态。您可以检查沙盒进行修复:https://codesandbox.io/s/loving-moon-0e91c

    检查 CheckBoxGroup.js 文件中的 onChildChangeonParentChange 方法

    【讨论】:

    • @RezaGhorbani 我直接在CheckBoxGroup.js 中引用状态,例如在第 7 行。我使用的是 let childSelected = props.state; 而不是 let childSelected = { ...props.state };
    猜你喜欢
    • 2021-01-22
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多