【问题标题】:React does not re-renderReact 不会重新渲染
【发布时间】:2016-05-09 00:14:01
【问题描述】:

我有带排序功能的 React 类 (List) 和简单元素的 React 类 (Elem)。如果排序功能启动,它将对状态数组中的元素进行排序并重新渲染列表,但保持不变,尽管状态数组已更改。代码:

var Elem = React.createClass({
    getInitialState() {
        var elem_name = this.props.name;
        return {
            name: elem_name
        }
    },
    render() {
        return <div>{this.state.name}</div>;
    }
});

var List = React.createClass({
    getInitialState() {
        return {
            received: false,
            arr: null
        }
    },
    receiving() {
        this.setState({
            received: true,
            arr: [1, 2, 3, 4, 5]
        });
    },
    sorting(type) {
        var self = this;
        return function() {
            function sort_func() {
                //sorting...
            }
            var main_arr = self.state.arr;
            main_arr.sort(sort_func);
            self.setState({
                arr: main_arr
            })
        }
    },
    render() {
        if(this.state.received) {
            var all_elems = [];
            this.state.arr.forEach(function(elem) {
                all_elems.push(<Elem name={elem}>);
            });
            return <div>
                <button onClick={this.sorting}>Sort</button>
                {all_elem}
            </div>
        }
        else {
            this.receiving();
            return <div>Empty</div>;
        }
    }
});

例如排序后的数组是[5, 4, 3, 2, 1]。最初的 HTML 页面是

<div>1</div><div>2</div>...<div>5</div>;

但排序后的 HTML 页面保持不变,虽然数组的状态发生了变化。

【问题讨论】:

  • 给你的元素一个独特的key属性。除非你需要修改它,否则避免将 prop 复制到 state (props.name => state.name)
  • 看起来你正在使用 ES6!请使用arrow functions 而不是self = this

标签: javascript reactjs render state


【解决方案1】:

我已经重构了你的代码,因为在你的版本中有几个错误

  1. Elem 你不需要使用state
  2. 您可以在getInitialState 中将初始数据添加到arr,而不是使用this.receiving();,并避免在render 方法中使用if/else
  3. 用`.map代替this.state.arr.forEach更合适
  4. arrow functions代替var self = this;

    var Elem = React.createClass({
      render() {
        return <div>{ this.props.name }</div>;
      }
    });
    
    var List = React.createClass({
      getInitialState() {
        return {
          received: false,
          arr: [1, 2, 3, 4, 5]
        }
      },
    
      sorting(type) {
        this.setState({
          received: !this.state.received,
          arr: this.state.arr.sort((a, b) => {
            return !this.state.received ? b - a : a - b;
          })
        })
      },
    
      render() {
        var elements = this.state.arr.map((elem, index) => {
          return <Elem name={elem} key={index} />
        });
    
        return <div>
          <button onClick={this.sorting}>Sort</button>
          { elements }
        </div>;
      }
    });
    

Example

【讨论】: