使用immutable.js在Redux中操作嵌套数组中的数据
Manipulating data in nested arrays in Redux with immutable.js
因此,我一直在用React Native制作一个应用程序,为此我用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的解决方案,但它非常丑陋,我真的不确定这是否是可行的。
我一直在寻找解决方案,但还没有找到一个不规范数据结构的解决方案。现在,我想看看是否可以避免对数据进行规范化,因为我想保持将内容发布回服务器的相同格式。(用于学习目的)
我的Reducer中的immutable.js解决方案如下:
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)]}))]}))]
}
当数据变得有点太深时,您仍然可以使用像Immutale.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)
,它希望传递一个普通对象,所以一定要传递一个纯对象,而不是一个不可变对象。
你说你并没有专门寻求数据格式本身的优化。如果我错了,请纠正我,我认为normalizer将帮助您获得平面度,并更容易更新您的商店
- 从多维嵌套json数组创建下拉列表
- 如何通过json对象数组为嵌套对象赋值
- 为循环嵌套的Javascript未按预期返回数组
- 具有嵌套对象数组的 Javascript 对象的递归搜索函数
- 将js对象更改为使用嵌套的可观察数组敲除js视图模型
- MongoDB嵌套对象数组后查询
- 从对象数组中动态创建嵌套json
- 使用Angular.js解析JSON中的嵌套对象数组
- 如何将id数组与带下划线的对象数组嵌套属性进行比较
- 将JS对象数组转换为嵌套形式的最有效方法
- 在javascript/angular中创建播放列表(按值复制数组,但按引用设置嵌套对象)
- 嵌套在 ng 重复中的拼接数组
- 嵌套/同心组和mouseenter/mouseleve
- javascript获取嵌套子数组中的对象
- 嵌套捕获组结果
- 如何在嵌套级别不受限制的情况下显示对象的动态嵌套子数组对象
- 按嵌套子数组对 arr 进行排序
- 播放框架 - 表单不绑定到嵌套元组
- 遍历嵌套到组和节中的一组输入
- 在数组和嵌套子数组中搜索Lodash属性