将状态作为道具从父母传递给孩子,然后在提交时从孩子更新父母

时间:2019-07-30 19:50:31

标签: reactjs

我有一个父组件,它呈现一个子组件并将其初始状态传递给该子组件。我需要澄清一下-我的直觉是要处理Child组件中的事件更改,这是正确的吗?提交后,如何将更新的道具传回给父母?我的直觉还告诉我们,一旦将道具传递回父对象,我就可以使用componentDidUpdate()设置要在其他地方使用的状态。如果可以,怎么办?

class Parent extends React.Component {
  constructor() {
    super();

    this.state = {
      arrival: "arrival",
      departure: "destination"
    };
  }

  componentDidUpdate(){
      // how to update state?
  }

  render() {
    const { arrival, departure } = this.state;
    return <Child arrival={arrival} departure={departure} />;
  }
}



class Child extends React.Component{
  constructor(){
    this.handleSubmission = this.handleSubmission.bind(this);
  }


  handleSubmission(e){
    const target = e.target;
    const name = target.name;
    const value = target.value;

    // not sure how to handle props from here
   }


  render(){
    let { arrival, departure } = this.props;
    return(
      <form onSubmit = {this.handleSubmission} >
        <div class="form-group">
          <label for="departure">Departure</label>
          <input type="" class="form-control" name="departure" aria-describedby="emailHelp" placeholder="Enter Departing Station"/>
        </div>
        <div class="form-group">
          <label for="arrival">Arrival</label>
          <input type="password" class="form-control" name="arrival" id="inputArrival" placeholder="Enter Arriving Station"/>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
      </form>
    )
  }
}

export default Child

2 个答案:

答案 0 :(得分:1)

只需将有关如何更新状态的参考传递给您的孩子:

2

答案 1 :(得分:1)

@hello_there

请忽略前面的答案,因为它不仅需要更改一些道具,还需要更多的东西。

我已经分叉了沙箱,并在此处重写了它(以便您可以继续使用)。
Edit so.answer.57279072

我已经概述了使更改传播到下面的父级的步骤。

捕获<input />

的状态

第一步是捕获表单字段的状态。
处理表单字段有两种方法

  1. Controlled Components
  2. Uncontrolled Components-不鼓励

我将使用前者(受控)通过向Form组件添加状态来捕获表单字段状态。

您需要为每个表单字段设置每个状态的value={...}并从onChange事件(使用下面添加的handleInputChange)更新每个状态。

我在进行更改的地方添加了

import React, { Component } from "react";

class Form extends Component {
  // .. ?
  state = {
    departure: "",
    arrival: ""
  };

  //... rest removed for brevity

  // .. ? is used to update each form field state.
  handleInputChange = e => {
    e.preventDefault();
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };


  render() {
    const { departure, arrival } = this.state;

    return (
      <form onSubmit={this.handleSubmission}>
        <div className="form-group">
          <label> Departure</label>
          <input
            className="form-control"
            name="departure"
            placeholder="Enter Departing Station"
            // ... ?         ...?
            value={departure} onChange={this.handleInputChange}
          />
        </div>
        <div className="form-group">
          <label> Arrival</label>
          <input
            className="form-control"
            name="arrival"
            id="inputArrival"
            placeholder="Enter Arriving Station"
            // ... ?        ...?
            value={arrival} onChange={this.handleInputChange}
          />
        </div>
        <button type="submit" className="btn btn-primary">
          Submit
        </button>
      </form>
    );
  }
}

更新App的状态更改事件处理程序

现在我们可以方便地使用状态,我们需要更新App的{​​{1}}来接受一个全新的状态,因此我们不进行多个方法调用(updateState)它会让我们传递一个新的引用,以便React知道this.props.updateParentState组件中的状态已更改。

App

更新 class App extends Component { constructor() { super(); this.state = { arrival: "arrival", departure: "departure" }; } // From this ? // updateState = (name, value) => { // this.setState({ // [name]: value // }); // }; // to this ? updateState = newState => this.setState(newState); componentDidUpdate(prevProps, prevState) { const { arrival, departure } = this.state; console.log(`Arrival: ${arrival}, departure: ${departure}`); } render() { const { arrival, departure } = this.state; return ( <Fragment> <Form arrival={arrival} departure={departure} // ? stays the same updateParentState={this.updateState} /> </Fragment> ); } } 的提交事件处理程序

现在Child接受一个状态对象,该状态对象可用于更新App.updateState,让我们更改App.state

Child.handSubmission

您会看到 handleSubmission = e => { e.preventDefault(); // this.props.updateParentState(name, value); this.props.updateParentState(this.state); }; 已被this.props.updateParentState(name, value)取代,这使我们可以立即更新this.props.updateParentState(this.state)

现在您应该可以在App.state中看到更改了。

working demo





旧答案-忽略此

更改子级中的状态不会导致父级中的重新渲染(因此App.componentDidUpdate可能不是由子级组件的更改触发的)。因此,您可以做的是将事件处理程序传递给子级,该子级可以通知父级组件发生了某些更改。

我已经解释了如何更新父级状态的流程。

首先,您需要创建一个处理程序,使用该处理程序可以更新父级的状态。

componentDidUpdate

在这里,我正在使用updateState = (name, value) => this.setState({ [name]: value }); ,这是一个动态属性。因此,它应该与父级的州名匹配。在这种情况下,[name]arrival

然后,您需要将该事件处理函数传递给Child(您可以将prop名称命名为任意名称(在下面的代码中,我使用了departure,但只要您通过正确地updateParentState)。

updateWhatever

这是将更新父状态的完整代码。 更改用下面的“?”表情符号表示。

updateState

如果使用prop-drilling难以管理语句管理,那么您可以伸出手来Context API(熟悉它之后,可以签出使用钩子的How to use React Context effectively) 。 或者,您可以使用Redux