Reactjs——父、子——每个的状态处理架构

标签 reactjs

我正在开发一个reactjs网站,该网站将提供一系列项目来填充表格。

父 shell 会将可用记录列表下拉到一个数组中 - 并使用子组件,我想用这些数据填充表行。

我已经开始创建子组件 - 但直到我将状态处理放置在渲染函数附近时,父组件提供的属性才会被处理。

我确实在子组件设置状态中有一个构造函数,但它没有看到要走的路——我应该在 componetDidMount 或 componentWillMount 中设置状态(——如果创建了一个新的子组件?)

子组件将具有按钮 - 保存、生成、取消 - 然后需要更改初始加载状态 -

//规则 父级可以创建/删除子级 - 从数组中 - 子级需要获取父级给出的初始值 - 但随后独立于父级进行操作 - 因此子级可以获取初始属性,然后使用其中的按钮 - 进行自己的调用。应用程序已受此父数组绑定(bind),这会导致故障。

-- child 需要能够取消 - 例如恢复到保存之前的原始状态 - 所以如果它被触摸 - isDirty 则为 true。 -- 一个老 child - isNew: false - 预先存在的数据 - 只显示一个保存按钮。仅名称可编辑 -- 一个新的子级 -- isNew: true -- 首先将显示一个生成按钮(保存隐藏) -- 如果用户手动开始在名称字段中输入数据,则生成按钮将被隐藏,并且将显示保存。 -- 在用户选择区域之前,生成/保存按钮将被禁用。

https://codesandbox.io/embed/frosty-vaughan-kdl1v 应该看起来像这样 - 一旦初始数组创建了子级 - 父级应该只能添加空白子级或删除新/旧子级 - 所有其他状态应该仅发生在子级级别 - 因为你可能有 3 个新 child ,5 个老 child - 开始更改值 - 有些被保存,有些被取消 - 独立更改..

父级

import React, { Component } from "react";

import Child from "./Child";
export default class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [
        {
          name: "apple",
          currentCode: "BJ3343",
          previousCode: " ",
          region: "opt2",
          isNew: false,
          isDirty: false
        },
        {
          name: "cherry",
          currentCode: "AS3433",
          previousCode: " ",
          region: "opt1",
          isNew: false,
          isDirty: false
        }
      ]
    };
  }

  addChild() {
    let blank = {
      name: "xxxxxxxxxxxxxxx",
      code: "",
      region: "",
      isNew: true,
      isDirty: true
    };

    this.state.list.push(blank);
  }

  render() {
    return (
      <div>
        <button onClick={this.addChild()}>Add Child</button>
        <button>Remove Child</button>
        <table>
          <thead>
            <tr>
              <td />
              <td>Region</td>
              <td>Code</td>
              <td>Name</td>
              <td>save/generate</td>
              <td>cancel</td>
            </tr>
          </thead>
          <tbody>
            {this.state.list.map((item, index) => {
              return (
                <Child
                  key={index}
                  index={index}
                  item={item}
                />
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }
}

child

//import ReactDOM from 'react-dom';
import React, { Component } from "react";

export default class Child extends Component {
  generateCode = index => {
    //does an api call -- and then on success alters the value of the code
    //Make an api call here and suppose api call return code 213
    const responseCode = 231;
    return responseCode;
  };

  saveCode = index => {
    //does an api call -- and then on success makes the child isDirty: false, isNew: false
  };

  cancel = index => {
    //reverts states for this child
  };

  render() {
    const index = this.props.index;
    const { name, region, currentCode, isNew, isDirty } = this.props.item;

    return (
      <tr>
        <td>
          <input type="checkbox" name="selection" />
        </td>
        <td>
          <select disabled={!isNew} type="input" name="region" value={region}>
            <option value="">Select</option>
            <option value="opt1">opt1</option>
            <option value="opt2">opt2</option>
            <option value="opt3">opt3</option>
            <option value="opt4">opt4</option>
          </select>
        </td>
        <td>
          <input disabled={!isNew} type="input" value={currentCode} />{" "}
        </td>
        <td>
          <input type="input" name="name" value={name} />
        </td>
        <td>
          <button onClick={() => this.generateCode(index)}>Generate</button>
          <button onClick={() => this.saveCode(index)}>Save</button>
        </td>

        <td>
          <button onClick={() => this.cancel(index)}>Cancel</button>
        </td>
      </tr>
    );
  }
}

//最新2019年9月30日 https://codesandbox.io/embed/elated-raman-twdqr

^ 将添加/删除子项——要为后端删除的模拟数据库数组

//最新2019年10月1日 https://codesandbox.io/s/stupefied-hodgkin-iyj43 - 最新版本 - 更稳定

最佳答案

您需要将状态向上移动到父级,并从父级在子级中访问它,如更新的答案所示。更多详细信息可以在这里找到Lifting up state official reactJS documentation 。或者您可以使用集中式状态管理库,例如 reduxmobx .

class Parent extends React.Component {
//define your parent as well as child state here. 
state={
  parentState={...},
  childState={name: '', region: ''}
}

handleChange = (newValues) => {
  this.setState({childState: newValues});
  // fetch data here and update it to the state
  fetch(){}
}

componentDidMount(){
  //fetch side effects here like data fecthing and setting state isLoading false here using setState
}

render() {
  if (this.state.isLoading){
    return (
      <p>Loading</p>
    )
  }
  return (
    <div>
      {
        this.state.cart.map((item, key) =>
            <Child key={item.id}
                name=item.name
                region=item.region
                values: {this.state.childState}
                handleChange={this.handleChange}
            />
        );
      }
    </div>
  );
}
}


class Parent extends React.Component {
render() {
  // directly access data using props instead of state
  // pass the updated value upwards to the parent via this.props.handleChange(newValue)(depends on your implementation)
  // Access new value in the child in next render by this.props.childState
  return (
    <div>
      <p>Name: {this.props.values.name}</p>
      <p>Region: {this.props.values.region}</p>
    </div>
  );
}
}

关于Reactjs——父、子——每个的状态处理架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58152125/

相关文章:

javascript - 在 React js 中使用 D3Funnel 时,TypeError : this. querySelectorAll 不是函数

javascript - 获取导致 React 闪烁的输入值

mysql - React-Admin 演示项目正在使用的 SQL 数据库

javascript - 提交后清除url

javascript - React 中的双面输入 slider

node.js - package.json 中的所有包都包含在 React 构建中吗?

reactjs - Material 界面 : Display sub-element on hover of parent

android - 如何为内容创建带有虚线 borderbottom 的自定义文本输入?

javascript - webpack动态导入.json文件?

reactjs - create-react-app Jest 遇到了意外的 token {