React:使用或不使用Immutable.js [英] React: use or not to use Immutable.js

查看:224
本文介绍了React:使用或不使用Immutable.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用React.js时,我一直在寻找Immutable.js的动机.据我了解,React.js应该保证属性的不变性.但是,我可以在此演示中更改视图属性:

I've looked for Immutable.js motivation when using React.js. As I understand React.js should guarantee immutability of properties. But, I can change view properties 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起(即将发布),属性将是不可变的.


Update: thanks to @FelixKling, now I know that properties will be immutable since React v0.14 (which is comming soon).

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

Question: What's the motivation to use Immutable.js with React v0.14?

Update2::我们真的可以更改父级的属性吗?在SubComponent中

Update2: Can we really change parent's properties? in SubComponent

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

推荐答案

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

After facing all rakes with react pure rendering I want to say that Immutable.js is not about providing deepEqual method. The main point is to clone state on each modification.

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

一切顺利,直到视图的状态仅由原始值组成.但是可能会发生的一件事是数组或复杂的对象树.

Everything goes well till view's state consists of primitive values only. But one moment that may happen it be an array or complex object tree.

假设您有一个视图YourView,该视图从商店YourStore中获取一个数组.并且您不想使用Immutable.js,只需包含Node.LS的deepEqual.例如:

Suppose you have a view YourView which takes an array from a store YourStore. and you don't want to use Immutable.js, just include Node.LS's deepEqual. For instance:

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:您应该期望_array[action.index].value = action.flag;将更新YourView,但不会.因此,ComponentComponentUpdate返回false而不是true .这不是因为shouldComponentUpdate将返回false.

Problem #1: shouldComponentUpdate return false instead of true you expect that _array[action.index].value = action.flag; will update YourView, but it doesn't. It doesn't because shouldComponentUpdate will return false.

原因是数组仅是一个引用,并且在this.setState({array: YourStore.getArray()})时,this.state.array(先前的状态)也被更新.这意味着在shouldComponentUpdate方法this.state和内部; nextState引用将指向同一对象.

The reason is that array is just a reference, and at the moment of this.setState({array: YourStore.getArray()}) this.state.array (previous state) is also updated. That means that inside shouldComponentUpdate method this.state & nextState refs will point to the same object.

问题1#解决方案:

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

You need to copy array reference before update it (i.e. with help of 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的多个值:

Suppose you need to update multiple values of _array inside if statements:

   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. 它具有批处理更新,因此您不必担心多次克隆数组

这篇关于React:使用或不使用Immutable.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆