首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Redux normalizr +处理减少的响应

Redux normalizr +处理减少的响应
EN

Stack Overflow用户
提问于 2016-07-01 05:01:44
回答 2查看 1.8K关注 0票数 7

Normalizr擅长创建实体的结构化JSON存储库。

我们有很多例子显示数据列表,例如已经标准化的posts。在列出posts的地方,are仅限于几个关键字段。

我们也有显示其中一个posts的情况,尽管我们现在需要从包含所有字段的API中获取完整的JSON实体。

怎样才能最好地处理这件事?

A是一种分离的减速器,雷鸣/传奇,选择器和动作?

B简单地将从API获取的post扩展版本插入到还原器中。重复使用以前的选择器等?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-01 14:58:38

把应用程序的状态想象成一个数据库。我建议你使用这种状态形状:

代码语言:javascript
复制
{
  entities: {
    // List of normalized posts without any nesting. No matter whether they have all fields or not.
    posts: {
      '1': {
        id: '1',
        title: 'Post 1',
      },
      '2': {
        id: '2',
        title: 'Post 2',
      }
    },
  },
  // Ids of posts, which need to displayed.
  posts: ['1', '2'],
  // Id of full post.
  post: '2',
}

首先,我们正在创建我们的normalizr模式:

代码语言:javascript
复制
// schemas.js
import { Schema, arrayOf } from 'normalizr';

const POST = new Schema('post');
const POST_ARRAY = arrayOf(POST);

在成功响应之后,我们正在对响应数据进行规范化处理,并发送以下操作:

代码语言:javascript
复制
// actions.js/sagas.js
function handlePostsResponse(body) {
  dispatch({
    type: 'FETCH_POSTS',
    payload: normalize(body.result, POST_ARRAY),
  });
}

function handleFullPostResponse(body) {
  dispatch({
    type: 'FETCH_FULL_POST',
    payload: normalize(body.result, POST),
  });
}

在减速器中,我们需要创建entities减缩器,它将侦听所有操作,如果它在有效负载中有entities键,则会将这些实体添加到app状态:

代码语言:javascript
复制
// reducers.js
import merge from 'lodash/merge';

function entities(state = {}, action) {
  const payload = action.payload;

  if (payload && payload.entities) {
    return merge({}, state, payload.entities);
  }

  return state;
}

此外,我们还需要创建相应的还原器来处理FETCH_BOARDSFETCH_FULL_BOARD操作:

代码语言:javascript
复制
// Posts reducer will be storing only posts ids.
function posts(state = [], action) {
  switch (action.type) {
    case 'FETCH_POSTS':
      // Post id is stored in `result` variable of normalizr output.
      return [...state, action.payload.result];
    default:
      return state;
  }
}

// Post reducer will be storing current post id.
// Further, you can replace `state` variable by object and store `isFetching` and other variables.
function post(state = null, action) {
  switch (action.type) {
    case 'FETCH_FULL_POST':
      return action.payload.id;
    default:
      return state;
  }
}
票数 8
EN

Stack Overflow用户

发布于 2016-08-06 10:39:47

我同意你们两种选择,并得出同样的结论。但让我们仔细看看它们,看看它们之间的优势:

(B) --您可以将post实体(预览和完全表示)合并为还原器中的一个实体,但您将跟踪result数组(预览和完全表示),这将在API请求之后从规范化数据中获得。然后,如果你已经有了文章的全部表示,那么你就可以很容易地分辨出来。您的子状态可能如下所示:

代码语言:javascript
复制
const postState = {
  // merged results from PREVIEW api
  previews: [1, 2, 3],

  // merged results from FULL api
  full: [2],

  // all merged entities
  entities: {
    1: {
      title: 'foo1'
    },
    2: {
      title: 'foo2',
      body: 'bar',
    },
    3: {
      title: 'foo3'
    }
  }
}; 

(A)您将有两个还原器+动作,每个表示都有一个,以区分实体。根据预览或完整的posts请求,您可以通过一个显式操作为您的减速器提供服务。你的亚州可能看起来像这样:

代码语言:javascript
复制
const previewPostState = {
  // merged results from PREVIEW api
  result: [1, 2, 3],

  // all preview entities
  entities: {
    1: {
      title: 'foo1'
    },
    2: {
      title: 'foo2',
    },
    3: {
      title: 'foo3'
    }
  }
}; 

const fullPostState = {
  // merged results from FULL api
  result: [2],

  // all full entities
  entities: {
    2: {
      title: 'foo2',
      body: 'bar'
    }
  }
}; 

从非常高的角度来看,您已经可以看到您必须保存重复的信息。带有id: 2的post实体将通过其title属性保存两次:一次用于previewPostState,一次用于fullPostState。如果要在全局状态中更改title属性,则必须在两处进行更改。一个人会违反“Redux”中唯一的真理来源。这就是我选择(B)的原因:您有一个位置供您的post实体使用,但是可以通过结果数组清楚地区分它们的表示。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38137381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档