This is something I'am not getting right.
While using redux, in reducers we use the spread operator.
For e.g.
{...state,data : action.payload,fetching:false}
That is a new state object is created, rather than mutating the correct state right? (Please correct me if i'am wrong)
In such cases what is the use of immutableJS ??
It performs the same action as mentioned above right??
You are correct, the example you have shown is creating a new object and not mutating the state. It is fine for many cases, so if you don't feel that ImmutableJS is going to add anything for you, don't use it.
ImmutableJS was more useful before the spread operator was in common use in ES6 (I believe it is technically still only a proposal). If you are not using ES6, then the alternative is to use Object.assign which can get very messy, very quickly, especially with more nested structures.
ImmutableJS is still useful if you need to modify a single node deep within the state tree, but if this is the case, you can generally get around it by structuring the data in a different way.
When you have a simple flat state, you can easily manage it without extra libraries.
But let's consider something more complex, like the following
{
users: {
123: {
name: 'John',
lastName: 'Doe'
},
345: {
name: 'Bob',
lastName: 'Jack'
}
....
}
}
If you want to update a name for some user, it will be not so trivial
return {
...state,
users: {
...state.users,
[action.userId]: {
...state.users[action.userId],
name: action.newName
}
}
Pretty much code, isn't it? At this moment, you may want to look for another solution and immutable.js may help you do the same with one line:
state.setIn(['users', action.userId, 'name'], action.newName)
Making your state immutable ensures you that the state will not get modified outside of flux-flow. In very complex structures with a lot of levels and props being passed around it, it prevents the state from being mutated accidentally.
Related
I'm new to React and I am creating an application where I am using a quite big state with frequent updates. Using useState() I understand it will replace the whole object on every update. If that means it will make a full copy of the object, there will be a severe performance hit in m case. If it is some lazy evaluation, I think I might be fine, hence my question.
Contrary, if I would use the old class based setState() method, I could update only the necessary parts of the state. For instance, my data structure looks something like this:
{
'data0': { ... some not very deep object ...},
'data1': { ... },
'data2': { ... },
...,
'dataN': { ... },
}
where I can potentially have thousands of data objects. As the data objects are quite small, replacing them when needed is not that much of a performance hit, which is perfectly doable with setState() in a class, but how is this going to work if using the useState() hook?
U can spread previous state with usestate and u will get same result as setstate
Usestate([
...state,
Data6
])
I'm coding an application using React for UI, Redux to manage the state and Immutable.js to mutate the state, however, I'd like to know how to avoid the use of Immutable.JS accessors in my React components, like get() or getIn().
I believe that using that Immutable.JS accessors will infect my React components. How to avoid that?
I don't think you're going to have much in the way of an option here if you want to keep it immutable. You could convert it toJS, but then you'd be losing the benefits of object identity comparison for re-rendering pure components. Your best bet is probably to hold your nose and pretend it's basically a JavaScript Map.
Aside from that, if you're not attached to Immutable.js, you might consider using something like seamless immutable which behaves a lot more like native JavaScript arrays and objects. Or you could go old-fashioned and just Object.freeze() things yourself.
The way to avoid Immutable.JS accessors and use the dot-notation is using the Record structure from Immutable.JS.
First we must create a template:
const MyTemplate = Record({
id: 0,
name: ''
})
...
case ContentFilterTypes.ADD_ITEM:
return {
listObjects : state.listObjects.push(new MyTemplate({
id: action.item.id,
name: action.item.description,
}))
}
To access it in the presentional, we need only to set the prop that we want to get information, like:
<ContentFilterAvatar id={value.id} name={value.name} />
What if I have very common situation like.
users:[
{
firstName:'Jack',
lastName:'Daniels'
}
]
I want to have getFullName, method, what is a proper way to do that in Redux, we all know that it's possible to make it markup. I have very complicated data structures and it's not that easy to make it in markup
In JavaScript, there is no need to couple the data and the methods that act on that data. Redux stores an immutable state object without methods. You just need to find somewhere else to put those methods. In this case, I would create a utils/people.js that exposes all the methods that are required to work on people. You can then pass the state from redux to that method and get everything you need.
Assuming your state in Redux looks something like:
{ firstName: 'John', lastName: 'Smith' }
You can have utils/people.js:
exports getFullName(state) {
return `#{state.firstName} #{state.lastName}`;
}
Given my initial redux state is :
const state = {
currentView: 'ROOMS_VIEW',
navbarLinks: List([
{name: 'Rooms', key: 'ROOMS_VIEW'},
{name: 'Dev', key: ''}
]),
roomListsSelected: {group: 0, item: 0},
roomLists: [
{
name: "Filters",
expanded: true,
listItems: [
{ icon: 'images/icon-warning.svg', name: 'Alerts', filter: room => room.hasAlert },
{ icon: 'images/icon-playlist.svg', name: 'In Progress', filter: room => room.progress > 20 },
{ icon: 'images/icon-playlist.svg', name: 'Almost Done', filter: room => room.progress > 90 },
{ icon: 'images/icon-playlist.svg', name: 'Complete', filter: room => room.status === 'complete' },
{ icon: 'images/icon-playlist.svg', name: 'Recently Completed', filter: room => false },
{ icon: 'images/icon-playlist.svg', name: 'All Rooms', filter: room => true }
]
}
],
rooms: List(generateRooms())
}
I need to make a reducer that does this:
state.roomList[n].expanded = !state.roomList[n].expanded
I am new to using a Redux workflow and the best way to solve this is to make roomList an immutable.js object or write some code to make a deep clone of my state object.
Also state.roomList will have new data pushed to it from future features.
Summery / Question: What is the best way to return a new state object in a reducer when making changes like this deep in the state, or should I change the structure of the Redux state object?
What I did In the end Immutable seems the way to go. There are some tricks with Immutable to reduce react rendering time and it meets all the project requirements. Also it is early enough in the project to use a new library without making major changes.
First, idiomatic Redux encourages you to "normalize" your state and flatten it as much as possible. Use objects keyed by item IDs to allow direct lookups of items, use arrays of IDs to denote ordering, and anywhere that one item needs to refer to another, it only stores the ID of the other item instead of the actual data. That allows you to do simpler lookups and updates of nested objects. See the Redux FAQ question on nested data.
Also, it looks like you're currently storing a number of functions directly in your Redux state. Technically that works, but it's definitely not idiomatic, and will break features like time-travel debugging, so it's heavily discouraged. The Redux FAQ gives some more info on why storing non-serializable values in your Redux state is a bad idea.
edit:
As a follow-up, I recently added a new section to the Redux docs, on the topic of "Structuring Reducers". In particular, this section includes chapters on "Normalizing State Shape" and "Updating Normalized Data", as well as "Immutable Update Patterns".
Reducer composition:
De-compose your reducers into smaller pieces so that a reducer is small enough to deal with simple data structure. eg. In your case you may have: roomListReducer listItemsReducer listItemReducer. Then at each reducer, its going to make it much more easier for you to read which part of the state you are dealing with. It helps a lot because each of your reducer is dealing with small piece of data that you don't have to worry things like 'should i deep copy or shallow copy'.
Immutable
I personally don't use immutable.js because I prefer to deal with plain objects. and there are just too much code to change to adopt a new API. But the idea is, make sure your state changes are always done through pure functions. Therefore, you can just simply write your own helper functions to do what you want, just make sure that they are tested thoroughly when dealing with complex objects.
Or simply enough, you can always deep copy your state in each reducer, and mutate in the copy then return the copy. But this is obviously not the best way.
I'm new to ImmutableJS. My app implements large Redux Store & multiple react components.
Correct me if I'm wrong:
I understand that the benefits of Immutable is to protect Flux Store and to avoid unnecessary vDom rendering on component getting unchanged props.
To benefit from better rendering performance with ImmutableJS, shouldComponentUpdate() must be implemented.
What is the best implementation of this function?
I already found several implementations of it, all using shallowEqual() with some modifications:
Facebook implements shallowEqual for React and more I imagine.
Jurassix offers an implementation that implements shallowEqualImmutable. It the function from Facebook except that the is() function is replaced by the one given by ImmutableJS. The first equality is different too.
Dan does the same thing with a different shalllowEqual function that implement parts of the two previous implementation.
Someone knows which implementation I should use in my case? or none and implement specific shouldComponentUpdate()? I am slightly at a loss on this point
Thank you a lot for any help!!
I understand that the benefits of Immutable is to protect Flux Store and to avoid unnecessary vDom rendering on component getting unchanged props.
This is not really related to Immutable (if you mean the library). For example, you can use plain objects and arrays with Redux but since Redux asks you to never mutate them, you get pretty much the same benefits in most cases. So Immutable library can offer a nicer API for updating things immutably, but it is not required for performance optimizations if you don’t mutate plain objects or arrays.
To benefit from better rendering performance with ImmutableJS, shouldComponentUpdate() must be implemented.
Again, not really related to ImmutableJS, but yes, to benefit from immutability in props, you’d need to implement shouldComponentUpdate(). However if you use Redux you probably already use connect() from React Redux package which implements shouldComponentUpdate() for you for most cases. So you don’t really need to write it by hand for any connect() ed components.
Someone knows which implementation I should use in my case? or none and implement specific shouldComponentUpdate()? I am slightly at a loss on this point
If you don’t have performance problems, don’t use either. React by itself is fairly performant in most cases, and a connect() on top of it will add a good default implementation of shouldComponentUpdate().
For components that are not connect()ed but still get frequently updated, I would suggest you to use react-addons-shallow-compare. It is used by PureRenderMixin internally but since mixins are not really used in modern React APIs, a separate function can be more convenient.
If you want special support for Immutable.is, you can indeed use something like shallowEqualImmutable. It understands Immutable collections better, as it considers lists of the same values to be the same. At this point you would be better off profiling different implementations against your app, as the specifics can vary depending on your use case.
Don’t optimize prematurely, make sure this is an actual problem before solving it.
I was also using a large Redux Store, and found that using the Immutable.js can make the accessing of the state complicated, e.g., nested2.getIn(['a', 'b', 'd']) vs nested2.a.b.d; What I really need is to make sure I don't mutate the state in my reducers, and still be able to check the equality using === in the shouldComponentUpdate() method.
I have created https://github.com/engineforce/ImmutableAssign to fulfill my requirements. It is a light weigh immutable helper, which supports immutability and allows you to continue working with POJO (Plain Old JavaScript Object), so our React components can read the state as usual, e.g.,
return newState.a.b.d === oldState.a.b.d;
Example,
var iassign = require("immutable-assign");
var o1 = { a: { b: { c: [[{ d: 11, e: 12 }], [{ d: 21, e: 22 }]], c2: {} }, b2: {} }, a2: {} };
//
// Calling iassign() to push new item to o1.a.b.c[1]
//
var o2 = iassign(
o1,
function (o) { return o.a.b.c[1]; }, // get property to be updated
function (c) { // update select property
c.push(101);
return c;
}
);
// o2.a.b.c[1][1] === 101
// o1 is not modified
// o2 !== o1
// o2.a !== o1.a
// o2.a.b !== o1.a.b
// o2.a.b.c !== o1.a.b.c
// o2.a.b.c[1] !== o1.a.b.c[1]
// o2.a2 === o1.a2
// o2.a.b2 === o1.a.b2
// o2.a.b.c2 === o1.a.b.c2
// o2.a.b.c[0] === o1.a.b.c[0]
// o2.a.b.c[0][0] === o1.a.b.c[0][0]
// o2.a.b.c[1][0] === o1.a.b.c[1][0]