所以,我一直在努力在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)]}))]}))]
}
答案 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将帮助您获得平坦感并更容易更新您的商店