What are the advantages of using Immutable with React (and optionally, Redux)? In Redux, I can simply use rest this in my reducers to return a new state:
const initialState = {
activeTrackId: '',
state: 'stopped',
};
export default function (state = initialState, action) {
switch (action.type) {
case actions.PROCESS_TRACK_ACTION:
return {
...state,
activeTrackId: action.state !== 'stopped' ? action.track._id : '',
state: action.state,
};
// ...
The only scenario I've found it useful in was this:
shouldComponentUpdate(nextProps) {
const oldProps = Immutable.fromJS(this.props);
const newProps = Immutable.fromJS(nextProps);
return !Immutable.is(oldProps, newProps);
}
And that might even be misusing it, as far as I know.
Maybe someone could enlighten me as to the advantage of using Immutable in the context of React and Redux?
The main reason Redux is using immutability is that it doesn't have to traverse an object tree to check for the changes in every key value. Instead, it will only check the object's reference is changed or not in order to update DOM on state change.
For redux to work correctly, the state must be immutable. This means that whenever we update the redux state, we have to create a copy of the whole state and set values to fields we want to change.
Immutable. js is a library designed for the creation of immutable collections of data. It is commonly used in React/Redux development. Immutable.
It means that once created data cannot be changed. It makes maintaining immutable data structures easier and more efficient. The tool supports data structure like: List, Map, Set and also structures that are not implemented in . js by default but can be very useful: OrderedMap, OrderedSet and Record.
There's a great video on the benefits and implementations for immutable data, from Lee's talk at React Conf 2015. As far as thinking about Immutable Data and React, I'd consider it essential viewing.
That aside, here are a few of my own thoughts on the matter.
The more complex your state becomes, the harder it becomes to manage it with literals and the spread operator. Imagine that rather than being flat, you had a few levels of nested state:
const initialState = {
core: {
tracker: {
activeTrackId: '',
state: 'stopped'
}
}
};
Although it's still possible to use the spread operator, it starts to become tedious.
return {
...state,
core: {
...state.core,
tracker: {
...state.core.tracker,
activeTrackId: action.state !== 'stopped' ? action.track._id : '',
state: action.state
}
}
};
Now look at the equivalent with Immutable.js.
import { Map } from 'immutable';
const initialState = Map({
core: Map({
tracker: Map({
activeTrackId: '',
state: 'stopped'
})
})
});
Then we can use the persistent API to make deep changes to the structure.
return state
.setIn(
['core', 'tracker', 'activeTrackId'],
action.state !== 'stopped' ? action.track._id : ''
)
.setIn(
['core', 'tracker', 'state'],
action.state
);
It's worth mentioning that depending on the shape of your state, it might make more sense to split and nest your reducers instead.
When you make a modification to an object with ImmutableJS it makes use of the fact that it's implemented with hash mapped vector tries to share most of the structure between the old object and the modified version.
When you use the spread operator to create new literals, you are forced to copy more data than you need to produce a new object.
You can eliminate a huge class of bugs by guaranteeing that the object can't be mutated.
With mutable state, its possible to pass an object reference out to some other code, which could mutate it. Mutating an object isn't "an error", so you won't be told that it's changed and there'll be no stack trace either, meaning it can be very hard to work out where the mutation is coming from.
Wherever your immutable objects go, they'll be safe.
You can use Immutable data structures to make more advanced decisions about whether to update components or not.
shouldComponentUpdate(nextProps) {
const oldProps = Immutable.fromJS(this.props);
const newProps = Immutable.fromJS(nextProps);
return !Immutable.is(oldProps, newProps);
}
Although these sorts of deep comparisons might seem expensive, they prevent you from needing to diff or touch the DOM when the objects haven't changed.
This will be even more effective if your props themselves are immutable objects, as fromJS
won't have to recreate the nested levels.
If you are careful, not to mutate the passed property, you don't have to use Immutable.js.
Since the props
are reference any changes to it would affect the whole application.
Immutable.js guarantees that they can not be modified but it has a performance impact on large apps if you are not performing mutation, but the benefit is, it prevents any accidental pollution of the application state.
You could check out these videos for a in depth explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With