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} />
Related
I am developing a React Native App and I am implementing my redux store.
And I was wondering if I can store a React Component in the redux initial state like this in my reducer :
import Tache from '../components/Tache';
const initialState = {
tache : [
<Tache props={{
nom : "Nom",
id: "0",
isDetail : false,
parentFunction : ()=> {return null},
listeMembre : ["Hugo", "Theo"],
desc : "Description",
date : "Date",
url : "www"
}}/>
]
}
It works for me but I am wondering if it's a good practise or not at all
Redux is just javascript. You can put whatever you want in there - functions, Dates, Sets, even entire component trees.
However, if you ever want to persist your state - i.e. save it to the device when the app is backgrounded, and reload it when the app is foregrounded - the data must all be serializeable. That means that JSON.parse(JSON.stringify(data)) must return the original data. This only works on primitives, and arrays and objects that hold primitives.
That's why it's considered bad practice to put anything else into your state. It also keeps your state from having "too much responsibility"; your state should tell your components what to display, and not handle any of the actual display.
No, Very bad practice. You should store only data in the redux not the jsx code.
why do you want to do this? I don't think that's the best practice, if you want to use the component multiple times you can implement conditional logic for that and make this component dependent on its result.
Redux or any global state management library is just for data management(add/delete/update etc), not for components storing.
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.
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}`;
}
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]
I've noticed that React only freezes the props shallowly, and that React.cloneElement only merges in props shallowly. So should we only be passing in props shallowly when we can?
You can definitely pass objects in props, I don't think it is a bad practice at all, although it's a good idea to define PropTypes on your component so that its users know what to pass in.
I'd also suggest looking into making your model immutable. Immutable objects are always 'frozen', plus they have other benefits, like allowing you to implement shouldComponentUpdate in a very efficient way, do deep comparison / deep cloning trivially etc. This kind of thing plays really well with react.
I would say try to make them shallow when possible, but it really isn't feasible to always do that because you'd have to assume your data is super flat. On top that, react allows for you to pass objects with shape, so I imagine its ok to pass and object in.
For example, look at the Animal object below.
{
name: 'Cow',
sound: 'Moo',
size: {
height: 50,
width: 200
},
origin : {
location: {
lat: 42.42,
lng: 83.02
},
name: 'Cow Land'
}
}
You may decide to build out an animal card that takes in an object. It may have a specific shape that has most of these props.
Within the card, you may want to use most of the properties. However, location is a nested object and may also be described with maybe a location component you have.
At some point, your data is going to have to come in from somewhere. If this animal object is part of a larger one, then passing in single props by dotting into the nested paths would be too burdensome and bloat one component too much.
I would suggest being clear about what your objects look like when they go down the component chain. Components are supposed to be composable so I would also imagine just breaking things down as much as possible. A component may be made of smaller components which handle the nested structure of data. From there, keeping to unidirectional data flow will help make it so your data is immutable.
Ultimately, use your discretion on deciding when you should be passing in primitive values verses maybe an object with shape.
The react examples show a bit of both.
var ProductRow = React.createClass({
render: function() {
var name = this.props.product.stocked ?
this.props.product.name :
<span style={{color: 'red'}}>
{this.props.product.name}
</span>;
return (
<tr>
<td>{name}</td>
<td>{this.props.product.price}</td>
</tr>
);
}
});
In this example, they are dotting on the product which is on the props. So this component is taking in a product object with an assumption of what is on it.
Good luck!