React.js,通过onChange事件重新呈现Child Component

时间:2017-09-22 11:42:36

标签: reactjs components

我是React.js的新手,但我喜欢研究新的东西并坚持这项任务。我有两个分层组件,当我更新父级状态时,子组件不会重新呈现。

我在父级中有onChange事件的元素。当发生更改时,我正在从REST请求JSON并在父级设置状态。然后在这个方法中,我正在调用具有由更改状态组成的数据属性的子组件的渲染。没有任何反应。它只发生在ONCE。选择下一个选项并不会做任何事情。

有经验的人可以快速查看我的代码并向我解释如何实现它。

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

import $ from "jquery";
import './App.css';
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import cafeList from "./cafeList.json";

class App extends Component {
  render() {
    return (
      <div className="App container">
        <div className="App-header">
          <h2>Dining Rooms Menu </h2>
        </div>
        <CafeSelect />
      </div>
    );
  }
}

class CafeSelect extends Component{
  constructor(props) {
    super(props);
    this.state = {
      cafeList: cafeList,
      goods_for_current_cafe: []
    };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(){
    var self = this;
    var cur_val_cafe = $('#select-cafe-type').find(":selected").val();
    console.log(cur_val_cafe);
    $.ajax({
      url: 'https://example.com/rest',
      type: 'POST',
      data: {
        auth: 'authkey',
        getcafeguide: 1,
        idpoint: cur_val_cafe,
      },
    })
    .done(function(res) {
      var data = $.parseJSON(res);
      self.setState({
        goods_for_current_cafe: data
      });

      console.log(self.state);
      ReactDOM.render(
        <GoodsGroup
          data={self.state.goods_for_current_cafe}
        />,
        document.getElementById("goods-group")
      );
    })
  }

  render() {
    return(
      <div>
        <div className="row">
            <label className="col-lg-2">Choose dining room</label>
            <div className="control-wrapper col-lg-10">
              <select className="form-control" id="select-cafe-type" onChange={this.handleChange}>
                {cafeList.map(function(cafe, index){
                      return <option key={ index } value={cafe.IDPoint}>{cafe.Point}</option>;
                })}
              </select>
            </div>
          </div>
        <div id="goods-group"></div>
        <div id="goods-list"></div>
      </div>
    )
  }
}

class GoodsGroup extends Component{
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(){
    var cur_group_val = $('#select-goods-type').find(":selected").val();
    var matches = $.grep(this.props.data, function(e) { return e.GoodsGroup == cur_group_val });
    ReactDOM.render(
      <GoodsList
        data={matches}
      />,
      document.getElementById("goods-list")
    );
  }

  componentWillMount() {
    console.log(this.props.data);
    let _ = require('underscore');
    var data = this.props.data;

    let categories = _.keys(_.countBy(data, function(data) {
      return data.GoodsGroup;
    }));
    this.setState({
       categories: categories,
       goods: this.props.data
    });

  }

  render() {

    return (
      <div className="row">
        <label className="col-lg-2">Choose goods category</label>
        <div className="control-wrapper col-lg-10">
          <select className="form-control" id="select-goods-type" onChange={this.handleChange}>
          {this.state.categories.map(function(group, index){
                    return <option key={ index } value={group}>{group}</option>;
              })}
          </select>
        </div>
      </div>
    )
  }
}


export default App;

2 个答案:

答案 0 :(得分:1)

这是 mvp 更改以使其正常工作。

在您的GoodsGroup组件中,将componentWillMount函数更改为以下

prepareData() {
    console.log(this.props.data);
    let _ = require('underscore');
    var data = this.props.data;

    return _.keys(_.countBy(data, function(data) {
        return data.GoodsGroup;
    }));
}

并且您的渲染功能必须更改为

render() {
    const categories = this.prepareData();
    return (
        <div className="row">
            <label className="col-lg-2">Choose goods category</label>
            <div className="control-wrapper col-lg-10">
                <select className="form-control" id="select-goods-type" onChange={this.handleChange}>
                    {categories.map(function (group, index) {
                        return <option key={index} value={group}>{group}</option>;
                    })}
                </select>
            </div>
        </div>
    )
}

解释

取自ReactDom.render

  

如果React元素先前已渲染到容器中,则会对其执行更新,并仅根据需要改变DOM以反映最新的React元素。

由于在重新渲染时GoodsGroup组件已存在,因此不会调用componentWillMount函数。所以我们改变它以便总是在渲染时调用。

答案 1 :(得分:1)

componentWillMount - 生命周期方法仅适用于 ONCE ,即安装发生时,componentWillMount内的状态更改不会触发重新呈现请参阅https://facebook.github.io/react/docs/react-component.html#componentwillmount 对于您的方案,在首次选择期间已经发生了安装。

尝试使用以下,

选项1:使用shouldComponentUpdate并在render()

下移动类别获取方法
getCategories() {
  const data = this.props.data;
  return _.keys(_.countBy(data, (data) => data.GoodsGroup))
}

shouldComponentUpdate(nextProps) {
  return !R.equals(this.props, nextProps)// using ramda for comparison 
}

render() {
  const categories = this.getCategories()

return (
    <div className="row">
        <label className="col-lg-2">Choose goods category</label>
        <div className="control-wrapper col-lg-10">
            <select className="form-control" id="select-goods-type" onChange={this.handleChange}>
                {categories.map(function (group, index) {
                    return <option key={index} value={group}>{group}</option>;
                })}
            </select>
        </div>
    </div>
)

选项2:否则使用componentWillReceiveProps()

getCategories(props) {
  const data = props.data;
  return _.keys(_.countBy(data, (data) => data.GoodsGroup))
}

componentWillMount() {
 const categories = this.getCategories(this.props)
 this.setState({
   categories: categories,
   goods: this.props.data
  })
}

componentWillReceiveProps(nextProps) {
  const categories = this.getCategories(nextProps)
  this.setState({
   categories: categories,
   goods: nextProps.data
  })
}

render() {

return (
    <div className="row">
        <label className="col-lg-2">Choose goods category</label>
        <div className="control-wrapper col-lg-10">
            <select className="form-control" id="select-goods-type" onChange={this.handleChange}>
                {this.state.categories.map(function (group, index) {
                    return <option key={index} value={group}>{group}</option>;
                })}
            </select>
        </div>
    </div>
)