Как передать измененное состояние от дочернего компонента его родителю в ReactJS - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь понять, как передать измененное состояние от дочернего компонента его родителю в ReactJS? пока следующий код изменяет дочернее состояние, но не родительское состояние, какая-либо подсказка, что я делаю неправильно?

Я использую redux, чтобы получить массив продуктов из mongodb.

Пример массива продуктов:

[
    {
        “_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>
      )
    }
  }

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Дочерний компонент может обновить родительский компонент двумя способами:

  1. Без использования Redux вы можете передать функцию в качестве подпорки дочернего компонента, чтобы дочерний компонент мог вызывать эту функцию для обновления родительского компонента.

  2. Сохраните данные в хранилище Redux. Дочерний компонент отправляет действие, которое обновляет состояние Redux, где родительский компонент получает данные.

0 голосов
/ 06 сентября 2018

Вы должны передать ребенку функцию.

В дочернем компоненте вы устанавливаете состояние равным значению реквизита, а затем обновляете состояние. Это не имеет никакого отношения к родительскому классу - вы также не должны изменять реквизиты так же, как в стороне.

Решение состоит в том, чтобы передать функцию от родителя к потомку. Эта функция обновит родительское состояние, и поскольку вы передаете родительское состояние дочернему, оно также будет обновлено.

Итак, в своем родительском классе вы могли бы сделать что-то вроде:

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)}
/>

Дочерний компонент не требует отслеживания всех состояний.

0 голосов
/ 06 сентября 2018

Простой пример объясняет концепцию передачи измененного состояния от дочернего к родительскому.

Компонент А:

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); это делается при визуализации непосредственно в любом обработчике событий, если вы хотите передать обновленное состояние

Как уже упоминалось @Ying zuo, вам нужно использовать redux, чтобы получить измененное значение состояния дочернего компонента в родительском компоненте.

Когда состояние изменяется в дочернем компоненте, вы выполняете вызов действия приведения, передавая значение в качестве параметра и устанавливая его в состоянии в редукторе, и получаете состояние в родительском компоненте

Надеюсь, что это объясняет концепцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...