javascript - react : use or not to use Immutable. js

标签 javascript reactjs immutable.js

我在使用 React.js 时寻找了 Immutable.js 的动机。据我了解,React.js 应该保证属性的不变性。但是,我可以更改 View 属性 in this demo :

var Hello = React.createClass({
    render: function() {
        var item = { prop: 128 };
        return <Test item={item} />;
    }
});

var Test = React.createClass({

    render: function() {
        this.props.item = -2; // Don't throw any error
        return <div>{this.props.item}</div>; // Returns -2 instead of object
    }
});

React.render(<Hello name="World" />, document.getElementById('container'));

更新:感谢@FelixKling,现在我知道自 React v0.14(即将推出)以来,属性将是不可变的。

问题Immutable.jsReact v0.14 一起使用的动机是什么?


更新2:我们真的可以改变父级的属性吗?在子组件中

let somePropVal = { a: 1 };
<SubComponent someProp={somePropVal} />
//....Then in SubComponent
this.props.someProp.a = 2; // somePropVal.a still will be `1` at parent element

最佳答案

在使用纯渲染进行 react 后,我想说 Immutable.js 并不是提供 deepEqual 方法。要点是在每次修改时克隆状态。

为什么需要在每次修改时克隆状态?

一切顺利,直到 View 的状态仅由原始值组成。但有一刻可能会发生它是一个数组或复杂的对象树。

假设您有一个 View YourView,它从存储 YourStore 中获取一个数组。并且您不想使用 Immutable.js,只需包含 Node.LS 的 deepEqual 即可。例如:

PureRenderMixin.js

const deepEqual = require('deep-equal');

module.exports = function pureRenderMixin(Component) {
    Component.prototype.shouldComponentUpdate = function(nextProps, nextState) {
        return !deepEqual(this.props, nextProps) || !deepEqual(this.state, nextState);
    };
    return Component;
};

YourView.react.js

class YourView extends React.Component {

    constructor(props) { 
        super(props);
        this._onChange = this._onChange.bind(this);
    }

    componentWillMount() {
        YourStore.addChangeListener(this._onChange);
    }

    _onChange() {            
        this.setState({array: YourStore.getArray()});
    }
}

module.exports = PureRenderMixin(YourView);

YourStore.js

......
getArray() { return _array; }

switch(action.type) {
   case ActionTypes.UPDATE_USER_FLAG:
       _array[action.index].value= action.flag; // BUG!!!
       YourStore.emitChange();
       break;
}

问题 #1:shouldComponentUpdate 返回 false 而不是 true 您期望 _array[action.index].value = action.flag; 将更新 YourView,但事实并非如此。事实并非如此,因为 shouldComponentUpdate 将返回 false

原因是 array 只是一个引用,在 this.setState({array: YourStore.getArray()}) 的时刻,this.state.array(之前的状态)也是更新。这意味着在 shouldComponentUpdate 方法中 this.statenextState refs 将指向同一个对象。

问题 1# 解决方案:

您需要在更新之前复制数组引用(即在 lodash 的帮助下):

YourStore.js

......
getArray() { return _array; }

switch(action.type) {
   case ActionTypes.UPDATE_USER_FLAG:
       _array = _.cloneDeep(_array); // FIXED, now the previous state will differ from the new one
       _array[action.index].value= action.flag; // BUG!!!
       YourStore.emitChange();
       break;
}

问题 #2:有时您需要多次克隆 _array,代码会出现错误

假设您需要更新 if 语句内 _array 的多个值:

   case ActionTypes.UPDATE_USER_FLAG:
       // You can't clone the _array once, because you don't know which conditions will be executed
       // Also conditions may not be executed at all, so you can't clone the _array outside of if statements
       if (someCondition) {
           _array = _.cloneDeep(_array);
           _array[someIndex].value= action.flag;
       }
       if (anotherCondition) {
           _array = _.cloneDeep(_array);
           _array[anotherIndex].value= action.flag;
       }
       YourStore.emitChange();
       break;

问题#2解决方案:使用Immutable.js。好处:

  1. 它具有清晰的界面,让您的大学清楚地知道每次都应该克隆状态
  2. 它具有批量更新功能,因此您不必担心多次克隆数组

关于javascript - react : use or not to use Immutable. js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32719425/

相关文章:

javascript - AngularJS:正确定义回调?

reactjs - 使用 React + Redux-ORM 的选择器。将数据传递给子组件

javascript - 如何使用 attachEvent 引用调用者对象 ("this")

javascript - 刚开始使用jwplayer,有几个问题

javascript - ComponentDidMount 没有被调用 - 非常简单的应用程序

ReactJs:将数据获取代码或副作用移至 componentDidUpdate

javascript - Immutable.js 中的 GroupBy,然后返回分组列表的第一个值

javascript - Immutable.is() 可以接受任何 Immutable 类型吗?

javascript - 如何使用 Immutable 删除深层属性

javascript - 附加外部 .json 的搜索结果