我是react / redux的初学者。
我已经在我的应用中完成了基本组件<HeatMap />
及其操作/减速器/存储,并且运行良好。
我将使用不同的设置(道具)渲染另一个<HeatMap />
。
我尝试做的是将这个2分量分开,因为当我dispatch
更新action
时,另一个同时执行。
我试过这个来分隔商店中的状态
import heatMap from './heat-map1'
import {combineReducers} from 'redux';
export let reducers = combineReducers({
heatMap1: heatMap,
heatMap2: heatMap
});
将RedReducers和connect
两个热图组合在商店中的不同对象
export default connect((state)=> {
return {
onState: state.heatMap1.onState,
config: state.heatMap1.config
}
})(CHMSHeatMap1)
和
export default connect((state)=> {
return {
onState: state.heatMap2.onState,
config: state.heatMap2.config
}
})(CHMSHeatMap2)
这是正确的吗?
因为2个组件在调度动作时都会反应
我正在考虑分离共享行动,但我认为这不是一个好主意。或者问题可能不在这里。
那么你能告诉我这个问题的原因以及解决方法吗?
这是我的减速机
import * as actionTypes from '../actions/heat-map';
import Immutable from 'immutable';
const onState = {
fetching: 'FETCHING',
error: 'ERROR',
drawn: 'DRAWN'
};
const initialState = {
onState: onState.fetching,
config: {}
};
export default function heatMapReducer(state = initialState, action) {
let immutableState = Immutable.fromJS(state);
switch (action.type) {
case actionTypes.INITIALIZING:
return immutableState.set('onState', onState.drawn).set('config', action.payload.initConfig).toJS();
case actionTypes.FETCH_DATA_REQUEST:
return immutableState.set('onState', onState.fetching).toJS();
case actionTypes.FETCH_DATA_SUCCESS:
return immutableState.set('onState', onState.drawn).setIn(['config','series',0,'data'],Immutable.fromJS(action.payload.mapData.data)).toJS();
case actionTypes.FETCH_DATA_FAILURE:
return immutableState.set('onState', onState.error).set('config', action.payload.mapData).toJS();
default:
return state;
}
}
行动很简单
export function initializeConfig(initConfig) {
return {
type: INITIALIZING,
payload: {
text: 'Initializing',
initConfig
}
}
}
export function requireMapData() {
return {
type: FETCH_DATA_REQUEST,
payload: {
text: 'Loading'
}
};
}
..........
//Async Action for fetching map data and redraw the map
export function fetchMapData(address) {
return function (dispatch) {
//dispatch requireMapData action to set the map in loading state
dispatch(requireMapData());
return fetch(address)
.then(fetchUtil.checkHttpStatus) //check if 404
.then(fetchUtil.parseJSON)
.then(mapData => dispatch(fetchDataSucceed(mapData)))
.catch(error => dispatch(fetchDataFailed(error)));
}
}
谢谢你我的朋友。
答案 0 :(得分:3)
您无法以您描绘的方式复制缩减器。两者都会以完全相同的方式对完全相同的行为做出回应。
解决方案是让所有热图数据处于相同的减速器状态。 e.g。
const initialState = {
heatMap1: {},
heatMap2: {}
};
export default heatmap(state = initialState, action) {
// etc
现在,如果您想对两个热图使用相同的操作,则需要有一个操作属性,指定您要定位的堆映射。如果您有多张热图,我建议使用一系列热图,每个动作包含index
或id
,以定位特定的热图。 e.g。
function updateHeatMap(index, value) {
return {
type: UPDATE_HEATMAP,
index: index,
value: value
}
}
答案 1 :(得分:2)
您还可以查看multireducer
模块(https://github.com/erikras/multireducer)。它旨在完全解决您提出的方案。
所以你可以这样配置你的商店:
import multireducer from 'multireducer';
import heatMap from './heat-map1'
import {combineReducers} from 'redux';
export let reducers = combineReducers({
multireducer: multireducer({
heatMap1: heatMap,
heatMap2: heatMap
})
});
之后,您需要使用connectMultireducer()
而不是redux的标准connect()
,以便将商店的特定切片连接到特定组件,如下所示:
export default connectMultireducer((state)=> {
return {
onState: state.heatMap.onState,
config: state.heatMap.config
}
})(CHMSHeatMap)
最后,为了获得每个组件的状态的正确部分,您在传递它们时将传递给它:
<CHMSHeatMap multireducerKey="heatMap1"/>
<CHMSHeatMap multireducerKey="heatMap2"/>
显然,最好在multireducer
回购中阅读实际的文档,但这应该给出一个简要的概述。基本上,该模块只是抽象了为通过multireducer
函数创建的每个reducer添加基于键的查找的过程。
答案 2 :(得分:0)
我建议使用没有任何库的多减速器的原始概念。
基本思想是独特的Symbol
动作类型和自包含的Redux模块,如下所示:
import * as services from './../../../api/services';
const initialState = {
list: [],
};
function getListReducer(state, action) {
return {
...state,
list: action.payload.list,
};
}
function removeItemReducer(state, action) {
const { payload } = action;
const list = state.list.filter((item, i) => i !== payload.index);
return {
...state,
list,
};
}
export default class List {
constructor() {
// action types constants
this.GET_LIST = Symbol('GET_LIST');
this.REMOVE_ITEM = Symbol('REMOVE_ITEM');
}
getList = (serviceName) => {
return async (dispatch) => {
const list = await services[serviceName].get();
dispatch({
type: this.GET_LIST,
payload: {
list,
serviceName,
},
});
};
}
removeItem = (index) => {
return (dispatch) => {
dispatch({
type: this.REMOVE_ITEM,
payload: {
index,
},
});
};
}
reducer = (state = initialState, action) => {
switch (action.type) {
case this.GET_LIST:
return getListReducer(state, action);
case this.REMOVE_ITEM:
return removeItemReducer(state, action);
default:
return state;
}
}
}
更多信息请参阅there。