使用immutable.js

时间:2016-05-11 18:59:45

标签: javascript redux immutable.js

所以,我一直在努力在React Native中创建一个APP,我用Java编写了一个RESTFul API,它以JSON格式返回一些数据。我将有一个看起来像这样的数据结构 - 它也是这个Reducer的初始状态,我只是删除了一些值,因为它们是无关紧要的:

categories: [{
    id: 1,
    name: '',
    image: '',
    subcategories: [
        {
            name: '',
            id: 1,
            products: [{
                name: '',
                description: 'This is a good product',
                id: 55,
                quantity: 4
            }, {
                name: '',
                description: 'This is a good product',
                id: 3,
                quantity: 0
            }]
        },
        {
            name: '',
            id: 2,
            products: [{
                name: '',
                description: 'This is a good product',
                id: 4,
                quantity: 0

            }]
        }]
}, {
    id: 2,
    name: '',
    image: '',
    subcategories: [
        {
            name: '',
            id: 3,
            products: [{
                name: '',
                description: 'This is a good product',
                id: 15,
                quantity: 0

            }]
        }

    ]
}]

我将在我的Redux商店保存这个,但是我要努力的是当我必须仅使用产品ID更新某个产品的数量时。 到目前为止,我已经找到了使用immutable.js的解决方案,但它非常难看,我真的不确定这是否可行。

我已经搜索了解决方案,但尚未找到一个没有规范化数据结构的解决方案。现在我想看看我是否可以避免规范数据,因为我想保持相同的格式将内容发回服务器。 (并用于学习目的)

我在使用immutable.js的Reducer中的解决方案如下所示:

case types.ADD_PRODUCT:

        const oldState = fromJS(state).toMap();

        var findCategoryIndex = oldState.get('categories').findIndex(function (category) {
            return category.get("subcategories").find(function (subcategories) {
                return subcategories.get("products").find(function (product) {
                    return product.get("id") === action.productId;
                })
            })
        })

        var findSubcategoryIndex = oldState.getIn(['categories', findCategoryIndex.toString()]).get('subcategories').findIndex(function (subcategory) {
            return subcategory.get("products").find(function (product) {
                return product.get("id") === action.productId;
            });
        })

        var findProductIndex = oldState.getIn(['categories', findCategoryIndex.toString(), 'subcategories', findSubcategoryIndex.toString()]).get('products').findIndex(function (product) {
                return product.get("id") === action.productId;
        })


        var newState = oldState.setIn(['categories', findCategoryIndex.toString(),
            'subcategories', findSubcategoryIndex.toString(), 'products', findProductIndex.toString(), 'quantity'],
        oldState.getIn(['categories', findCategoryIndex.toString(), 'subcategories', findSubcategoryIndex.toString(), 'products', findProductIndex.toString(), 'quantity'])+1);


        const newStateJS = newState.toJS();


        return {...state, categories: [...newStateJS.categories]}

我知道这一切看起来似乎过于复杂,但我只是想学习不同的方法,因为我对与JavaScript有关的一切都是新手。

我不是在寻找数据格式本身的优化,但我正在寻找在Redux中嵌套数组中操作数据的方法

我希望能得到一些很好的反馈意见,并希望了解我是否走在正确的轨道上:)

编辑:它可以在不使用Immutable.js的情况下使用扩展运算符,但我真的不明白它的区别。是否有性能差异以及为什么选择其中一个?

case types.ADD_PRODUCT:
        return {
            ...state,
            categories:[...state.categories.map(category => ({...category,
                subcategories:[...category.subcategories.map(subcategory => ({...subcategory,
                    products:[...subcategory.products.map(product => product.id === action.productId ? {...product, quantity: product.quantity+1} : product)]}))]}))]
        }

1 个答案:

答案 0 :(得分:3)

当数据变得有点太深时,您仍然可以使用Immutable.js Map之类的帮助程序。我不确定这是使用Immutable.js的正确方法,因为我也正在试验它。它允许您以一种不那么冗长的方式返回新状态:

import { fromJS } from 'immutable';

export default function reducer(state = initialState, action) {    
  const iState = fromJS(state);// Immutable State
  switch (action.type) {
    case type.ACTION:
      return iState.setIn(['depth1','depth2', 'depth3'], 'foobar').toJS() 
// return a copy of the state in JavaScript
// {depth1: {depth2: {depth3: 'foobar'} } }
  default:
    return state;
}

从我所听到的,使用Immutable更高效,但它为您的项目添加了另一个依赖项。如果你使用的是combineReducers(reducers)it expects to be pass a plain object,请小心,所以一定要传递普通对象而不是Immutable对象。

您说您并不是专门寻找数据格式本身的优化。如果我错了,请纠正我,我认为normalizr将帮助您获得平坦感并更容易更新您的商店