用父持有状态反应组件的层次结构

时间:2019-02-11 07:49:49

标签: reactjs react-redux react-state-management

我正在尝试为以下情况创建一个React SPA:  学校     -学生1     -学生2     -学生3          -名称          -地址              -门牌号,街道,城市,州,国家/地区。

如果我认为学校,学生,地址是反应的组成部分。 学校:拥有/显示学生列表,可以添加,删除。 学生:保留/显示可修改的信息,例如姓名,地址。 地址:保留/显示地址详细信息,可以修改。

现在,我该如何进行状态管理,例如,如果用户修改了其中一名学生的地址,这在学校中将如何体现。

我想到的

选项: 1.使用Redux,但说我想将此School创建为要在另一个react应用中使用的组件,我将能够在组件级别使用redux存储。

  1. 将Student对象传递给Student react组件,该组件将在修改道具时使用信息进行更新。

注意:我是新来的反应者,请问我写的东西不正确或没有道理。

import * as React from 'react';

export default class School extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      schoolName: "test school",
      students: [],
      update:false
    }
  }

  handleAddStudent = ()=>{
    let student = {
      name : "student1",
      className: "class1",
      address:{
        houseNumber :  "1-2/A-3",
        street: "street1",
        city: "city1",
        country: "country1"
      }
    }
    this.state.students.push(student);
    this.setState({ update: true});
  }

  handleToJson = () => {
    console.log(JSON.stringify(this.state));
  }

  render() {
    return (
    <div>
      <ul>{
        this.state.students.map((student)=>{
            return <Student student={student}/>
        })
      }
      </ul>
      <button onClick={this.handleAddStudent}>Add Student </button>
      <br/>
        <button onClick={this.handleToJson}>To json</button>
    </div>
    );
  }
}

export class Student extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      studentName: this.props.student.name,
      className: this.props.student.className,
      address: this.props.student.address
    }
  }

  handleChange = (e)=>{
    const value = e.target.value;
    switch(e.target.name)
    {
      case 'studentName':
        this.setState({ studentName: value});
        this.props.student.name = value;
        break;
      case 'className':
        this.setState({ className: value });
        this.props.student.className = value;
        break;
    }
  }

  render() {
    return (
      <div>
        <input name='studentName' value={this.state.studentName} onChange={this.handleChange} />
        <input name='className' value={this.state.className} onChange={this.handleChange} />
        <Address name='address' address={this.state.address}/>
      </div>
    );
  }
}

export class Address extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      houseNumber: this.props.address.houseNumber,
      street: this.props.address.street,
      city: this.props.address.city,
      country: this.props.address.country
    }
  }

  handleChange = (e) => {
    const value = e.target.value;
    switch (e.target.name) {
      case 'houseNumber':
        this.setState({ houseNumber: value });
        this.props.address.houseNumber = value;
        break;
      case 'street':
        this.setState({ street: value });
        this.props.address.street = value;
        break;
      case 'city':
        this.setState({ city: value });
        this.props.address.city = value;
        break;
      case 'country':
        this.setState({ country: value });
        this.props.address.country = value;
        break;
    }
  }

  render() {
    return (
      <div>
        <input name='houseNumber' value={this.state.houseNumber} onChange={this.handleChange} />
        <input name='street' value={this.state.street} onChange={this.handleChange} />
        <input name='city' value={this.state.city} onChange={this.handleChange} />
        <input name='country' value={this.state.country} onChange={this.handleChange} />
      </div>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

谢谢

1 个答案:

答案 0 :(得分:0)

首先,在React中使用本地状态很好。一般规则是将状态提升到一个依赖于它的每个组件都可以轻松访问它的级别。如果其中的数据仅对该特定组件重要,则将其保留在本地。

  

现在,我该如何进行状态管理,例如,如果用户修改了其中一名学生的地址,这在学校中将如何体现。

根据您的用例,将学生及其属性的列表保留在<School />组件中将是最有效的。这样一来,您就可以根据需要将其传递下去,而不必担心。

我注意到您在每个组件中都有本地状态,这是从其属性派生的。更有效的方法是简单地创建对道具的引用,并改为使用它们。

学校组件(保持原样)

学校应维护学生名单及其所有子属性。

学生和地址组成部分

这两个应该始终引用其道具,并调用父方法来更新状态。

代替

this.state = {
  studentName: this.props.student.name,
  className: this.props.student.className,
  address: this.props.student.address
}

只要做

const { name, className, address } = this.props.student;

在需要访问这些变量的任何函数中。

您应该将handleX类型的函数移到School中,并通过prop传递它。

您也可以跳过使用过多道具的操作,而仅使用Context API。例如...

//In parent

const ThemeContext = React.createContext('default value');

...
return (
  <SchoolContext.Provider value={this.state}>
    ...
  </SchoolContext.Provider>
)
...

//In any child
import Context from './School';

class ChildComponent extends React.Component {
  ...
}

ChildComponent.contextType = Context;

希望可以解决这个问题,如果您不了解某些内容,请告诉我。