【问题标题】:How to pass the changed state from child component to its parent in ReactJS如何在 ReactJS 中将更改的状态从子组件传递给其父组件
【发布时间】:2019-02-11 04:38:02
【问题描述】:

我想了解如何在ReactJS 中将更改的状态从子组件传递到其父组件?到目前为止,以下代码更改了子状态,但没有更改父状态,有什么线索我做错了吗?

我正在使用reduxmongodb 获取产品数组。

产品数组示例:

[
    {
        “_id”: “2331”, 
        “department”: “Shoes”,
        “category”: “Shoes/Women/Pumps”,
        “name”: “Calvin Klein”,
        “title”: “Evening Platform Pumps”,
        “description”: “Perfect for a casual night out or a formal event.”,
        “style”: “Designer”,
        "colors": ["red","yellow","red","black"]
    },

    {
      “_id”: “30671”, 
      “department”: “Shoes”,
      “category”: “Shoes/Women/Pumps”,
      “name”: “zara”,
      “title”: “Evening Platform Pumps”,
      “description”: “Perfect for a casual night out or a formal event.”,
      “style”: “Designer”,
      "colors": ["red","yellow","red","black"]
    }
]

父组件

  import React, { Component } from 'react'

  class Parent extends Component {
    constructor(props) {
      super(props);

      this.state = {
        products: [],
      };
    }

    componentDidMount() {
      this.props.getProducts();
    }

    componentDidUpdate(prevProps, prevState) {
      if (this.props.product.products !== prevState.products) {
        this.setState({ products: this.props.product.products });
      }
    }

    onUpdateProducts = (e) => {
      const newProducts = this.state.products;
      this.props.updateProductName(newProducts);
    };


    render() {
      const { products } = this.state;

      if (isEmpty(products)) {
        productContent = (
          <div>
            <p className="lead text-muted">Error Empty Products </p>
          </div>
        );
      } else {
        const productArr = products.map((product) => (
          <Child key={product._id} product={product} />
        ));

        productContent = (
          <div>
            {productArr}
          </div>
        );
      }

      return (
        <div className="container">
          {productContent}
          <div className="row">
              <div className="col-md-12">
                <button className="btn " onClick={this.onUpdateProducts}>
                  Submit
                </button>
              </div>
            </div>
        </div>
      )
    }
  }

  const mapStateToProps = (state) => ({
    product: state.product
  });

  export default connect(mapStateToProps, {
    getProducts,updateProductName
  })(Parent);

子组件

  import React, { Component } from 'react'

  export default class Child extends Component {
    constructor(props) {
      super(props);
      this.state = {
        product: this.props.product,
      };
    }

    componentDidUpdate(prevProps, prevState) {
      if (this.props.product !== prevProps.product) {
        this.setState({
          product: this.props.product
        });
      }
    }

    onChangeProductName = (e) => {
      const newProduct = Object.assign({}, this.state.product, {
        name: e.target.value
      });

      this.setState({ product: newProduct }, function() {
        console.log('onChangeProductName: ', this.state.product);
      });
    };

    render() {
      const { product } = this.state;
      return (
        <div>
          <TextInput
              placeholder="Product Name"
              name="prd_name"
              value={product.name}
              onChange={this.onChangeProductName}
            />
        </div>
      )
    }
  }

【问题讨论】:

  • 我认为你做错了,解决方案是从这些组件中删除状态,并通过 redux 处理产品名称更改 => 每次用户修改输入时调度一个动作,它可以使用像 redux-form 这样的库更容易实现

标签: reactjs redux components state


【解决方案1】:

你必须给孩子一个函数。

在子组件中,您将 state 设置为等于 props 值,然后您正在更新 state。这与父类无关 - 您也不应该修改 props 。

解决方案是将函数从父级传递给子级。这个函数会更新父状态,因为你将父状态传递给子状态,它也会被更新。

因此,在您的父类中,您可以执行以下操作:

onChangeProductName = (value, i) => {
  const new_product_array = [...this.state.products];
  new_product_array[i].name = value;

  this.setState({ products: new_product_array});
};

您需要将此传递给孩子

const productArr = products.map((product, i) => (
   <Child
      key={product._id}
      product={product} onChangeName={this.onChangeProductName.bind(this)}
      index={i} />
));

然后在孩子中调用它

<TextInput
  placeholder="Product Name"
  name="prd_name"
  value={product.name}
  onChange={() => this.props.onChangeName(product, this.props.index)}
/>

子组件就不需要所有的状态跟踪了。

【讨论】:

    【解决方案2】:

    一个简单的示例将解释将更改的状态从子级传递给父级的概念。

    组件 A:

    export default class A extends Component{
    
      //This is a callback
      handleStateChange = (value) ={
        console.log("value", value);//you get the value here when state changes in B(Child) component
      }
      render(){
        return(
          <div>
            <B handleStateChange={this.handleStateChange} />
          </div>
        )
      }
    }
    

    组件 B:

    export Class B extends Component{
      constructor(props){
        super(props);
        this.state={
           value: "01"
        }
      }
    
      handleButton = () => {
         const value = "02";
         this.setState({
           value: "02"
         });
         this.props.handleStateChange(value);
      }
      render(){
        return(
          <div>
            <button onClick={this.handleButton} />
          </div>
        )
      }
    }
    

    或者调用 this.props.handleStateChange(this.state.value); 也可以直接传递状态如果您想传递更新的状态,则 this 在任何事件处理程序上直接呈现

    正如@Ying zuo 所说,您需要使用redux 来获取父组件中子组件的更改状态值。

    当子组件中的状态发生变化时,您通过将值作为参数传递来进行 redux 操作调用,并将其设置为 reducer 中的状态并获取父组件中的状态

    希望能解释这个概念。

    【讨论】:

      【解决方案3】:

      子组件更新父组件有两种方式:

      1. 不使用Redux,可以传递一个函数作为子组件的prop,子组件可以调用这个函数来更新父组件。

      2. 将数据存储在 Redux 存储中。子组件调度一个更新 Redux 状态的操作,父组件在其中获取数据。

      【讨论】:

        猜你喜欢
        • 2017-05-31
        • 2019-02-17
        • 2020-07-04
        • 2022-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-02
        • 2019-08-15
        相关资源
        最近更新 更多