【问题标题】:When using Immutable.JS, should redux selectors always return Immutable.JS objects?使用 Immutable.JS 时,redux 选择器是否应该总是返回 Immutable.JS 对象?
【发布时间】:2018-04-18 17:47:35
【问题描述】:

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.

以官方shopping-cartdemo为例。选择器getCartProducts 同时使用状态的购物车切片和产品切片来构造返回对象:

export const getCartProducts = state =>
  getAddedIds(state).map(id => ({
    ...getProduct(state, id),
    quantity: getQuantity(state, id)
  }))

在这种情况下,如果使用 Immutable.JS,如何重构这个选择器,让它返回一个 Immutable.JS 对象?

【问题讨论】:

    标签: reactjs redux immutable.js reselect


    【解决方案1】:

    不改变状态很重要,但你可以在没有 Immutable.JS 的情况下做到这一点

    你不需要在 Redux 中使用 Immutable.JS。如果编写正确,纯 JavaScript 完全能够提供不可变性,而无需使用以不可变为中心的库。 redux faq

    【讨论】:

    • 我知道如何在没有不可变库的情况下编写不可变状态。但是我想知道在使用 Immutable.JS 时如何处理我的问题中提到的情况。这是我的问题。
    【解决方案2】:

    如果您将使用 Immutable JS 对象并在其上使用方法 .map,它将返回新的 ImmutableJs 对象。

    https://facebook.github.io/immutable-js/docs/#/Map/map

    如果你有 vanilla JS 对象并想将其转换为 Immutable.js 有辅助函数 fromJS() https://facebook.github.io/immutable-js/docs/#/fromJS

    let some = {foo: 'bar'};
    let immutableObject = Immutable.fromJS(some);
    

    如此多的选择。

    1. 确保您在 Immutable.js 结构上运行 map 函数

    2. 使用 Immutable.fromJS() 从 vanilla 转移到 Immutable.js 后按原样运行

    【讨论】:

    • 谢谢。但也许你没有明白我的意思。我的观点是,在使用 Immutable.JS 时,选择器是否应该始终返回 Immutable.JS 对象?在我提到的情况下,似乎选择器返回一个普通的 JS 对象更合理。
    • 如果你有 immutable.js 结构,它将返回 immutable.js 对象或节点值。如果节点值为js对象,则返回js对象。
    【解决方案3】:

    如果你的整个 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>

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 2018-10-02
      相关资源
      最近更新 更多