【问题标题】:React.js, rerender Child Component by onChange eventReact.js,通过 onChange 事件重新渲染子组件
【发布时间】:2018-03-03 23:42:48
【问题描述】:

我是 React.js 的新手,但我喜欢学习新的东西并坚持完成这项任务。我有两个分层组件,当我更新父组件的状态时,子组件不会重新渲染。

我在父元素中有 onChange 事件。发生更改时,我从 REST 请求 JSON 并在父级设置状态。然后在这个方法中,我使用包含更改状态的数据属性调用子组件的渲染。什么也没有发生。它只发生一次。下一个选项选择没有任何作用。

能否请更有经验的人快速查看我的代码并解释我必须如何实现它。

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;

【问题讨论】:

    标签: reactjs components


    【解决方案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 函数。所以我们改变它,让它总是在渲染时被调用。

    【讨论】:

    • 哦,天哪,非常感谢你!!!当你第一次面对编码中的新事物时,有些事情有时很难理解。抱歉 4 我的英语不好,不是母语人士。再次感谢你,你是最棒的!!!
    【解决方案2】:

    componentWillMount - 生命周期方法只会工作 ONCE 即当安装发生并且 componentWillMount 内部的状态更改也不会触发重新渲染参考 https://facebook.github.io/react/docs/react-component.html#componentwillmount 对于您的方案,安装已经在第一次选择期间发生。

    尝试在下面使用,

    方案一:使用 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>
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-06
      • 1970-01-01
      • 2018-08-12
      • 2019-06-01
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多