使用Immutable.JS时,redux选择器是否总是返回Immutable.JS对象?

时间:2017-11-06 14:23:21

标签: reactjs redux immutable.js reselect

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对象?

3 个答案:

答案 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);

所以几个选项。

  1. 确保在Immutable.js结构上运行地图功能

  2. 现在运行,在使用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>