NB: This is a question, very similar to Redux; accessing other parts... but it has nothing to do with Router :( thus cannot be solved same way
When I reduce one part of the state, I "feel" like I need to access other parts as well. I admit that I just might "misfeel" the core principals of the Redux, or have flaws in my app's architecture.
My current solution would be to modify github:combineReducers.js's code:
var finalState = mapValues(finalReducers, (reducer, key) => {
var previousStateForKey = state[key]
var nextStateForKey = reducer(previousStateForKey, action)
...
}
from
var nextStateForKey = reducer(previousStateForKey, action)
to
var nextStateForKey = reducer(previousStateForKey, action, state)
which would allow me to do what I need:
function reducer(state, action, root) {
if (root.otherPart.get("isSomething")) {
return state.set("anotherThing", true);
}
return state;
}
Question is if I am on the right way to do it, or is it something that should be solved using different architectural approaches, without having a need to access one part of state from other parts?
** UPDATE 5h Dec, 2018 **
Due to relatively high interest to this question (15 up-votes atm), I am adding my own answer below, hope it helps to those who is looking for that answer.
Intro
I'd like to add an answer, which is based on my 3y+ experience and also recaps some of the other answers and comments above (Thanks to all the contributors)
Short Answer
An original
combineReducers
can be used. Every selector works with Root State. Reducer mutates only it's part of the Root State. Reducer is as thin as possible, and only Action (or Thunk) is responsible for collecting all the data, needed to reduce the part of the Root StateDetailed Answer
Application's reducers, actions and selectors are organised using Ducks approach. Using Redux Thunk gives lot of benefits (thanks to Leonardo).
If we use definitions of my initial question, one single "Duck" - is "one part of the state", and it groups following major items:
%duckName%
, receives )type
,interface
,enums
)State of the application - is an object. It's keys - are the names of all the "Ducks" that participate in reducing application's state.
Reducers shall be kept as thin as possible, as Leonardo has advised.
All of the Actions and Thunks, can be split into following categories:
{ type: "%actionName%", payload: ... }
In some cases, you can have more than one Application in your codebase. Your Applications might share some of the Ducks. Sometimes you need to create Duck for every Application, so you can pass some configuration. But these are puzzles of a different story :)
I've tried to cover minimal portion of them in this repository, which I intend to keep contributing to. It's written using Typescript. I hope it makes it more easier to understand
I use Thunk to
getState()
, prepare the data from the full store, then dispatch an action.You can put the decision logic in the reducer or in the action. It is up to you. I prefer fat actions and thin reducers but there is no right/wrong.
Leonardo
You can try to use:
redux-named-reducers
Which allows you to get state anywhere in your code like so:
Works with combineReducers such that each reducer only handles local state but can access external state if needed.
You don't have to use
combineReducers()
.From the official Redux docs:
So your proposed solution is definitely one way you can do it.
Thanks to @MichelleTilley for spearheading the train of thought!