简体   繁体   English

当道具更改时,React 子组件不会重新渲染

[英]React Child Component not re-rendering when props change

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 checked value in the App.js state reflects the checkbox output ticks, but when the state is being modified by passing the setState as props to the child components, the checkboxes do not update.现在,在App.js状态中硬编码checked值反映了复选框输出刻度,但是当通过将setState作为道具传递给子组件来修改状态时,复选框不会更新。

One hacky way of partially solving what I'm trying to do, is by using a useState in the CheckBoxGroup.js onChange methods, to change a boolean value, thus forcing the component to update.部分解决我正在尝试做的事情的一种黑客方法是在CheckBoxGroup.js onChange 方法中使用useState来更改布尔值,从而强制更新组件。 But even then, the console shows the correct changed props.state, but the app.js component state doesn't reflect.但即便如此,控制台仍会显示正确更改的 props.state,但 app.js 组件状态并未反映出来。 Without the useState, the checkboxes do not seem to re-render as well.如果没有 useState,复选框似乎也不会重新渲染。 Can someone help with this please?有人可以帮忙吗? Thanks谢谢

The following is the code.以下是代码。 Code Sandbox link here: https://codesandbox.io/s/red-haze-ij1km?fontsize=14&hidenavigation=1&theme=dark代码沙盒链接在这里: https : //codesandbox.io/s/red-haze-ij1km? fontsize =14& hidenavigation =1& theme =dark

App.js应用程序.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 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复选框组.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复选框.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;

when you updating the state in onChildChange and onParentChange method you are referencing the same state.当您在onChildChangeonParentChange方法中更新状态时,您正在引用相同的状态。 You can check sandbox for fix: https://codesandbox.io/s/loving-moon-0e91c您可以检查沙箱进行修复: https : //codesandbox.io/s/loving-moon-0e91c

Check onChildChange and onParentChange method inside CheckBoxGroup.js file检查 CheckBoxGroup.js 文件中的onChildChangeonParentChange方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM