React 不会重新渲染

React does not re-render

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

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 页面保持不变,尽管数组状态发生了变化。

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

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

    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