两个减速器之间的共享状态

时间:2018-06-20 06:49:27

标签: reactjs redux react-redux

我有两个缩减器,第一个缩减器获取数据,第二个缩减器用于基于原始数据的更改来过滤数据。我已经读过,combineReducers不是一个选择。

我的postReducer

import {FETCH_POST} from '../actions/types';

const initialState = {
    items: [],
    item: {}
};

export default function(state = initialState, action){
    switch (action.type){
        case FETCH_POST:
            return Object.assign({}, state, {items: action.payload});
        default:
            return state;
    }

}

我的pinReducer

import {PIN_POST} from '../actions/types';

const initialState = {
    items: [],
    item: {}
};

export default function(state = initialState, action){
    switch (action.type){
        case PIN_POST:
            console.log(state.items);
            const item = state.items.map(value => value.data.id === action.id ?
                {data: Object.assign({}, value.data, {pinned: action.val})} : value
            );
            //console.log(item);
            return Object.assign({}, state, {items: item });
        default:
            return state;
    }

}

主要

import {combineReducers} from 'redux';
import postReducer from './postReducer';
import pinReducer from './pinReducer';

export default combineReducers({
    post: postReducer,
    pin: pinReducer
});

由于pinReducer中的state.items为空,我如何在两个减速器之间共享状态

2 个答案:

答案 0 :(得分:1)

您不应该拥有具有基于其他减速器派生状态的减速器。在这种情况下,您需要的是一个选择器(更有效的是memoizedSelector),可以使用reselect

我的postReducer

import {FETCH_POST} from '../actions/types';

const initialState = {
    items: [],
    item: {}
};

export default function(state = initialState, action){
    switch (action.type){
        case FETCH_POST:
            return Object.assign({}, state, {items: action.payload});
        default:
            return state;
    }

}

主要

import {combineReducers} from 'redux';
import postReducer from './postReducer';

export default combineReducers({
    post: postReducer,
});

,然后在要使用pinItem的地方,可以在mapStateToProps

中进行操作
getPinItem = (state, props) => {
    const item = state.items.map(value => value.data.id === action.id ?
                {data: Object.assign({}, value.data, {pinned: action.val})} : value
    );
    return item;
}

const mapStateToProps = (state, props) => {
    const pinItem = getPinItem(state, props);
    return {
        pinItem
    }
}

答案 1 :(得分:0)

Reducer不能访问商店的状态,也不能访问其他Reducer的先前状态。仅恢复到其先前的状态并调度动作。您可以将其视为redux状态墙中的一块砖。

在您的情况下,我们必须解决逻辑并确定此处的实际状态。

要求:

  1. 获取帖子列表:状态是帖子数组;
  2. 固定这些帖子之一:state是当前固定的帖子的ID;
  3. 获取当前固定的帖子:按固定的帖子ID在数组中查找帖子。

解决方案:

1-初始职位减少者:

const initialState = { items: [] }

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_POSTS:
      return { items: action.payload }
    default:
      return state
  }
}

2-添加有关固定信息的信息:

const initialState = { items: [], pinnedId: null }

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_POSTS:
      return { ...state, items: action.payload.posts }
    case PIN_POST:
      return { ...state, pinnedId: action.payload.id }
    default:
      return state
  }
}

3-获取当前固定的帖子:

// assuming that store is configured...
export default combineReducers({ posts: postsReducer })
// ...

// somewhere in `connect`
const mapStateToProps = (state, ownProps) => {
  return {
    pinnedPost: state.posts.find(post => post.id === state.posts.pinnedId),
  }
}

因此,我们现在存储有关固定帖子的最少信息(仅存储其ID),足以获取实际的固定帖子。

此外,正如@ shubham-khatri在另一个答案中所述,您可以使用优化的选择器。由于状态的当前形状是分开存储固定ID的,因此它的效率更高,因为您的选择器将取决于两个输入:posts数组(在fetch上重新创建,因此比较浅)和固定ID(是原始数字或字符串,也很容易比较)。

我建议您尽可能少地在商店中存储信息。另外,将其以简单平坦的形状存储。将可以计算的所有内容移至选择器。