ngrx处理对象中的嵌套数组
ngrx dealing with nested array in object
我正在学习 redux 模式并将 ngrx 与 angular 一起使用 2. 我正在创建一个具有以下形状的示例博客网站。
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[];
}
我的减速器和动作如下:
import { ActionReducer, Action } from '@ngrx/store';
import * as _ from 'lodash';
export interface ActualContent {
id: string;
type: string;
data: string;
}
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[];
}
export const initialState: BlogContent = {
id: '',
header: '',
tags: [],
title: '',
actualContent: [],
};
export const ADD_OPERATION = 'ADD_OPERATION';
export const REMOVE_OPERATION = 'REMOVE_OPERATION';
export const RESET_OPERATION = 'RESET_OPERATION';
export const ADD_IMAGE_ID = 'ADD_IMAGE_ID';
export const ADD_FULL_BLOG = 'ADD_FULL_BLOG';
export const ADD_BLOG_CONTENT_OPERATION = 'ADD_BLOG_CONTENT_OPERATION';
export const ADD_BLOG_TAG_OPERATION = 'ADD_BLOG_TAG_OPERATION';
export const blogContent: ActionReducer<BlogContent> = (state: BlogContent= initialState, action: Action ) => {
switch (action.type) {
case ADD_OPERATION :
return Object.assign({}, state, action.payload );
case ADD_BLOG_CONTENT_OPERATION :
return Object.assign({}, state, { actualContent: [...state.actualContent, action.payload]});
case ADD_BLOG_TAG_OPERATION :
return Object.assign({}, state, { tags: [...state.tags, action.payload]});
case REMOVE_OPERATION :
return Object.assign({}, state, { actualContent: state.actualContent.filter((blog) => blog.id !== action.payload.id) });
case ADD_IMAGE_ID : {
let index = _.findIndex(state.actualContent, {id: action.payload.id});
console.log(index);
if ( index >= 0 ) {
return Object.assign({}, state, {
actualContent : [
...state.actualContent.slice(0, index),
action.payload,
...state.actualContent.slice(index + 1)
]
});
}
return state;
}
default :
return state;
}
};
这工作正常,但我不确定它是否是正确的方法,或者我是否应该以某种方式将 ActualContent 分离到它自己的 reducer 和动作中,然后将它们合并。
抱歉,如果这个 post 不属于这里,你可以指导我应该把这个 post 放在哪里,我会把它从这里删除。提前致谢。
P.S。我做了一些研究,但找不到任何有复杂嵌套对象的文章,所以我可以参考。请添加 ngrx 或相关主题的任何有用的博客链接,这可以帮助我。
而不是嵌套结构
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[]; <------ NESTED
}
你应该有一个正常的状态。
例如这里你应该有这样的东西:
// this should be into your store
export interface BlogContents {
byId: { [key: string]: BlogContent };
allIds: string[];
}
// this is made to type the objects you'll find in the byId
export interface BlogContent {
id: string;
// ...
actualContentIds: string[];
}
// ----------------------------------------------------------
// this should be into your store
export interface ActualContents {
byId: { [key: string]: ActualContent };
allIds: string[];
}
export interface ActualContent {
id: string;
// ...
}
因此,如果您尝试填充您的商店,它看起来像这样:
const blogContentsState: BlogContents = {
byId: {
blogContentId0: {
id: 'idBlogContent0',
// ...
actualContentIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
}
},
allIds: ['blogContentId0']
};
const actualContentState: ActualContents = {
byId: {
actualContentId0: {
id: 'actualContentId0',
// ...
},
actualContentId1: {
id: 'actualContentId1',
// ...
},
actualContentId2: {
id: 'actualContentId2',
// ...
}
},
allIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
};
在您的逻辑或视图中(例如 Angular),您需要嵌套结构以便迭代数组,因此您不想迭代 ID 的字符串数组。相反,你想要 actualContent: ActualContent[];
.
为此,您创建一个 selector
。每次您的商店发生变化时,您的选择器都会启动并生成新的 "view" 原始数据。
// assuming that you can blogContentsState and actualContentsState from your store
const getBlogContents = (blogContentsState, actualContentsState) =>
blogContentsState
.allIds
.map(blogContentId => ({
...blogContentsState.byId[blogContentId],
actualContent: blogContentsState
.byId[blogContentId]
.actualContentIds
.map(actualContentId => actualContentsState.byId[actualContentId])
}));
我知道一开始可能会处理很多,我邀请您阅读 official doc about selectors and normalized state
在学习 ngrx 时,您可能想看一下我制作的一个名为 Pizza-Sync 的小项目。 Code source is on Github. It's a project were I've done something like that to demo :). (You should also definitely install the ReduxDevTools app看看店里怎么样)。
如果您有兴趣,我制作了一个小视频,只关注 Redux with Pizza-Sync:https://youtu.be/I28m9lwp15Y
我正在学习 redux 模式并将 ngrx 与 angular 一起使用 2. 我正在创建一个具有以下形状的示例博客网站。
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[];
}
我的减速器和动作如下:
import { ActionReducer, Action } from '@ngrx/store';
import * as _ from 'lodash';
export interface ActualContent {
id: string;
type: string;
data: string;
}
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[];
}
export const initialState: BlogContent = {
id: '',
header: '',
tags: [],
title: '',
actualContent: [],
};
export const ADD_OPERATION = 'ADD_OPERATION';
export const REMOVE_OPERATION = 'REMOVE_OPERATION';
export const RESET_OPERATION = 'RESET_OPERATION';
export const ADD_IMAGE_ID = 'ADD_IMAGE_ID';
export const ADD_FULL_BLOG = 'ADD_FULL_BLOG';
export const ADD_BLOG_CONTENT_OPERATION = 'ADD_BLOG_CONTENT_OPERATION';
export const ADD_BLOG_TAG_OPERATION = 'ADD_BLOG_TAG_OPERATION';
export const blogContent: ActionReducer<BlogContent> = (state: BlogContent= initialState, action: Action ) => {
switch (action.type) {
case ADD_OPERATION :
return Object.assign({}, state, action.payload );
case ADD_BLOG_CONTENT_OPERATION :
return Object.assign({}, state, { actualContent: [...state.actualContent, action.payload]});
case ADD_BLOG_TAG_OPERATION :
return Object.assign({}, state, { tags: [...state.tags, action.payload]});
case REMOVE_OPERATION :
return Object.assign({}, state, { actualContent: state.actualContent.filter((blog) => blog.id !== action.payload.id) });
case ADD_IMAGE_ID : {
let index = _.findIndex(state.actualContent, {id: action.payload.id});
console.log(index);
if ( index >= 0 ) {
return Object.assign({}, state, {
actualContent : [
...state.actualContent.slice(0, index),
action.payload,
...state.actualContent.slice(index + 1)
]
});
}
return state;
}
default :
return state;
}
};
这工作正常,但我不确定它是否是正确的方法,或者我是否应该以某种方式将 ActualContent 分离到它自己的 reducer 和动作中,然后将它们合并。 抱歉,如果这个 post 不属于这里,你可以指导我应该把这个 post 放在哪里,我会把它从这里删除。提前致谢。
P.S。我做了一些研究,但找不到任何有复杂嵌套对象的文章,所以我可以参考。请添加 ngrx 或相关主题的任何有用的博客链接,这可以帮助我。
而不是嵌套结构
export interface BlogContent {
id: string;
header: string;
tags: string[];
title: string;
actualContent: ActualContent[]; <------ NESTED
}
你应该有一个正常的状态。
例如这里你应该有这样的东西:
// this should be into your store
export interface BlogContents {
byId: { [key: string]: BlogContent };
allIds: string[];
}
// this is made to type the objects you'll find in the byId
export interface BlogContent {
id: string;
// ...
actualContentIds: string[];
}
// ----------------------------------------------------------
// this should be into your store
export interface ActualContents {
byId: { [key: string]: ActualContent };
allIds: string[];
}
export interface ActualContent {
id: string;
// ...
}
因此,如果您尝试填充您的商店,它看起来像这样:
const blogContentsState: BlogContents = {
byId: {
blogContentId0: {
id: 'idBlogContent0',
// ...
actualContentIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
}
},
allIds: ['blogContentId0']
};
const actualContentState: ActualContents = {
byId: {
actualContentId0: {
id: 'actualContentId0',
// ...
},
actualContentId1: {
id: 'actualContentId1',
// ...
},
actualContentId2: {
id: 'actualContentId2',
// ...
}
},
allIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
};
在您的逻辑或视图中(例如 Angular),您需要嵌套结构以便迭代数组,因此您不想迭代 ID 的字符串数组。相反,你想要 actualContent: ActualContent[];
.
为此,您创建一个 selector
。每次您的商店发生变化时,您的选择器都会启动并生成新的 "view" 原始数据。
// assuming that you can blogContentsState and actualContentsState from your store
const getBlogContents = (blogContentsState, actualContentsState) =>
blogContentsState
.allIds
.map(blogContentId => ({
...blogContentsState.byId[blogContentId],
actualContent: blogContentsState
.byId[blogContentId]
.actualContentIds
.map(actualContentId => actualContentsState.byId[actualContentId])
}));
我知道一开始可能会处理很多,我邀请您阅读 official doc about selectors and normalized state
在学习 ngrx 时,您可能想看一下我制作的一个名为 Pizza-Sync 的小项目。 Code source is on Github. It's a project were I've done something like that to demo :). (You should also definitely install the ReduxDevTools app看看店里怎么样)。
如果您有兴趣,我制作了一个小视频,只关注 Redux with Pizza-Sync:https://youtu.be/I28m9lwp15Y