React ImmutableJS - ShouldComponentUpdate

时间:2016-06-16 08:10:51

标签: javascript reactjs immutable.js

父组件:

import React, { Component } from 'react';
import { Child } from './Child';

const testObject = {
  test: {
    one: false,
    two: false,
    three: false,
  },
};

export class Parent extends Component {
  constructor() {
    super();
    this.state = {
      test: testObject.test,
    };
  }

  render() {
    return (
      <Child test={ this.state.test } />
    )
}

子组件:

import React, { Component, PropTypes } from 'react';

export class Child extends Component {
  shouldComponentUpdate(nextProps) {
    return nextProps.test !== this.props.test;
  }

  render() {
    console.log('hey! i\'m rendering!!');
    return (
       <div>Child</div>
    );
  }
}

Child.propTypes = {
  test: PropTypes.object.isRequired,
};

问题: 现在,它不起作用。当让我们说test.one变为true时,shouldComponentUpdate仍会重新渲染。我阅读了关于immutablejs和反应文档的文档,但我仍然不理解。对你们来说应该很容易,有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

testObject不是一成不变的。当然它不能被另一个对象替换:testObject = anotherTestObject被禁止,但可以修改onetwothreetestObject.one = true就可以了。 ImmutableJS提供禁止testObject值修改的mecanismes。

调用SetState将创建一个新的this.state.test,因此,nextProps.test !== this.props.test始终会重新生成。

答案 1 :(得分:0)

您的组件会重新呈现,因为评估nextProps.test !== this.props.test将始终返回true,因为值或类型都不会更改。

您似乎只更改了one对象的twothreetest的属性值。这里的问题是你试图将一个对象的属性评估到另一个对象,而这不能用(严格)比较运算符(例如=====)来完成。

解决此问题的一种方法是将对象转换为JSON进行比较:

return JSON.stringify(nextProps.test) !== JSON.stringify(this.props.test);

另一个解决方案是逐个比较每个属性:

for(let key in this.props.test) {
  if(!(key in nextProps.test) || this.props.test[key] !== nextProps.test[key]) {
    return true; //the current property didn't evaluate - component should update 
  }
}
for(var key in nextProps.test) {
  if(!(key in this.props.test) || nextProps.test[key] !== this.props.test[key]) {
    return true; //the current property didn't evaluate - component should update 
  }
}
return false; //the objects are equal - component shouldn't update

编辑: Damien Leroux正确指出您的testObject是不可变的,因为您已将其声明为常量。你可能想改变它。