I am working on a React/Redux application that allows for \"widgets\" to be added to a page and manipulated in 2D space. It is a requirement that multiple widgets can be selecte
You can try to use:
redux-named-reducers
Which allows you to get state anywhere in your code like so:
const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)
Or to assign external dependent state to your reducers like so:
reducerA.extState1 = reducerB.state1
Then access it like so:
getState(reduerA.extState1)
This is a good use case for Reselect:
Create a selector to access your state and return derived data.
As an example:
import { createSelector } from 'reselect'
const widgetsSelector = state => state.widgets;
const selectedWidgetsSelector = state => state.selection.widgets;
function minCoordinateSelector(widgets, selected) {
const x_list = selected.map((widget) => {
return widgets[widget].x;
});
const y_list = selected.map((widget) => {
return widgets[widget].y;
});
return {
x: Math.min(...x_list),
y: Math.min(...y_list)
};
}
const coordinateSelector = createSelector(
widgetsSelector,
selectedWidgetsSelector,
(widgets, selected) => {
return minCoordinateSelector(widgets, selected);
}
);
The coordinateSelector
now provides access to your min x
and y
properties. The above selector will only be updated when either the widgetsSelector
or selectedWidgetsSelector
state changes, making this a very performant way to access the properties you are after and avoids duplication in your state tree.
I am using this:
CommonReducer.js
export default function commonReducer(state = initialState.doesNotMatter, payload) {
switch (payload.type) {
case "JOINED_TYPE": {
let newState = Object.assign({}, state);
return newState;
}
default:
return state;
}
}
SomeOtherReducer.js
import commonReducer from './commonReducer';
export default function someReducer(state = initialState.somePart, payload) {
switch (payload.type) {
case "CUSTOM_TYPE": {
let newState = Object.assign({}, state);
return newState;
}
default:{
return commonReducer(state, payload);
}
}
}
If you use the thunk middleware (https://github.com/gaearon/redux-thunk) you can make the SET_SELECTION
action a thunk, which will allow it to read entire state before making the dispatch that will be received by your reducer.
// action creator
function setSelection(selectedWidgetId) {
return (dispatch, getState) => {
const {widgets} = this.getState();
const coordinates = getSelectionCoordinates(widgets, selectedWidgetIds);
dispatch({
type: SET_SELECTION,
payload: {
widgets: selectedWidgets,
x: coordinates.x,
y: coordinates.y
}
});
}
This way you get all the information you need in your selection reducer without having to pass along the list of all widget-objects to your action.