Reputation: 885
The Redux Team suggests selectors always return Immutable.JS objects .However, I find it's difficult for selectors to return Immutable.JS objects when selectors' returning objects are constructed by multiple slices of the state.
Take the official shopping-cart demo as an example. The selector getCartProducts
uses both the cart slice and the product slice of the state to construct the returning object:
export const getCartProducts = state =>
getAddedIds(state).map(id => ({
...getProduct(state, id),
quantity: getQuantity(state, id)
}))
In this case, if using Immutable.JS, how to reconstruct this selector to let it return a Immutable.JS object?
Upvotes: 0
Views: 660
Reputation: 2272
If your whole redux state is an immutable.js object, all those functions are going to return an immutable.js object. Per example, getAddedIds(state)
function will return an Immutable.List and the map
function will return a new Immutable.List. As you shouldn't never mix plain JS objects with Immutable.js objects, the objects inside those Lists will be an Immutable.js as well.
I tried to create a simple example to show you how these selectors would look like
const ids = [
'a2ds2',
'a3322asdda',
'1d1w1s11x1'
];
const products = [{
id: 'a2ds2',
name: 'milk'
},
{
id:'a3322asdda',
name: 'bread'
},
{
id:'b1d1w1s11x1',
name: 'orange'
}
];
const cartItems = [
{
productId: 'a3322asdda',
qnt: 20
},
{
productId: 'a2ds2',
qnt: 3
}
]
const newState = Immutable.fromJS({
ids,
products,
cartItems
})
// returns an List of ids
const getAddedIds = (state) => state.get('ids').filter(id => id[0] === 'a')
// returns an product Map
const getProduct = (state, id) => state.get('products').find(product => product.get('id') === id)
// returns the qnt of a product
const getQntByProduct = (state, id) => state.get('cartItems').find(item => item.get('productId') === id).get('qnt')
// create the new List
const result = getAddedIds(newState)
.map(id => getProduct(newState, id).set(
'qnt',
getQntByProduct(newState, id)
)
)
console.log('result', result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>
Upvotes: 0
Reputation: 26423
If you will use Immutable JS object and use method .map on it, it will return new ImmutableJs object.
https://facebook.github.io/immutable-js/docs/#/Map/map
If you have vanilla JS object and want to convert it to Immutable.js there is helper function fromJS() https://facebook.github.io/immutable-js/docs/#/fromJS
let some = {foo: 'bar'};
let immutableObject = Immutable.fromJS(some);
so couple options.
make sure you are running map function on Immutable.js structure
run as it is now and after done transfer from vanilla to Immutable.js using Immutable.fromJS()
Upvotes: 0
Reputation: 10224
It is important to not mutate the state, but you can do this without Immutable.JS
You do not need to use Immutable.JS with Redux. Plain JavaScript, if written correctly, is perfectly capable of providing immutability without having to use an immutable-focused library. redux faq
Upvotes: 2