Redux团队建议selectors always return Immutable.JS objects 。但是,我发现当选择器'选择器返回Immutable.JS对象时很难。返回的对象由状态的多个切片构成。
以官方shopping-cart演示为例。选择器getCartProducts
使用购物车切片和州的产品切片来构造返回对象:
export const getCartProducts = state =>
getAddedIds(state).map(id => ({
...getProduct(state, id),
quantity: getQuantity(state, id)
}))
在这种情况下,如果使用Immutable.JS,如何重构这个选择器让它返回一个Immutable.JS对象?
答案 0 :(得分:2)
重要的是不要改变状态,但是你可以在没有Immutable.JS
的情况下做到这一点您不需要在Redux中使用Immutable.JS。简单的JavaScript,如果写得正确,完全能够提供不变性,而不必使用不可变的集中库。 redux faq
答案 1 :(得分:0)
如果您将使用Immutable JS对象并使用方法.map,它将返回新的ImmutableJs对象。
https://facebook.github.io/immutable-js/docs/#/Map/map
如果你有vanilla JS对象并希望将它转换为Immutable.js,则有来自JSS的辅助函数 https://facebook.github.io/immutable-js/docs/#/fromJS
let some = {foo: 'bar'};
let immutableObject = Immutable.fromJS(some);
所以几个选项。
确保在Immutable.js结构上运行地图功能
现在运行,在使用Immutable.fromJS()完成从vanilla转移到Immutable.js之后
答案 2 :(得分:0)
如果整个redux状态是一个immutable.js对象,则所有这些函数都将返回一个immutable.js对象。例如,getAddedIds(state)
函数将返回一个Immutable.List,而map
函数将返回一个新的Immutable.List。由于您永远不要将普通的JS对象与Immutable.js对象混合使用,因此这些列表中的对象也将是Immutable.js。
我试图创建一个简单的示例,向您展示这些选择器的外观
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>