How to access global state from redux-loop combineReducers? - redux

I'm using react-loop, and I'm trying to use its combineReducers but extend it to pass as a third parameter the global state, basically implementing an API similar to https://github.com/Velenir/combine-reducers-global-state
Combine reducers basically invokes the childReducers as we can find in its code
let currentChild = childReducer(prev[key], action, ...args);
The idea is to pass there a third parameter, so , action, plainState, ...args so that the reducer receive it as parameter. The problem is how to produce that plainState, since the rootState is basically a combination of array of the form ([state, Cmd]) instead I need only the plain state, without redux-loop handler variables.

You'd have to write your own version of combineReducers. The supplied one is not expected to work outside of the simplest case. You can base it off of the supplied one though. https://github.com/redux-loop/redux-loop/blob/master/src/combine-reducers.js. I imagine you can implement it similarly to the library you mentioned.
If you're looking for a way to inject other state values into a reducer though, check out this middleware that I've used with redux-loop for a few years now. https://github.com/bdwain/redux-action-enhancer
Disclaimer: I maintain both redux-loop and redux-action-enhancers.

Related

What data types can be passed to redux-thunk actions?

Problem overview
I am using redux-form, and it wraps my compoent, and provides as a property change() which is a bound function for changing the form. I wanted to invoke this in an actionCreator.
Issue
I thought I could just pass it to my actionCreator thunk, but it seems that the value is stripped on dispatch of the action.
Details
So what I tried instead of sending the bound action change I tried instead to send a pointer to one of my other actionCreators called act.setFMEPATH, but that is also not working.
In the first picture below I show the state of the variables in before the dispatach to the redux-action occurs. As you can see from the watch, act.setFMEPath clearly is defined.
In the second picture you see the state of the action when it is entered. defaultPath is define (it is scoped to a closure on the stack), but the storeAct.
In my code, I am hard coding the STORE.dispatch(Act.setFMEPath(filePath[0]) since the paramater storeAct is not visible, But what I want it STORE.dispatch(storeAct(filePath[0])
Should I be binding the context of the first parameter to the dispatch() and turning storeAct() into a bound function (but note it is an arrow function, so that is not going to work).
State before call:
State entry of pickFile action creator
The code which invokes pickFolder (i.e. Act.pickFolder(Act.setSourcePath, defaultPath)) has nothing to do with redux-thunk at all. It will be evaluated before redux-thunk will come into play, because of the way redux-thunk works.
redux-thunk checks if dispatched value was a function and if it was, redux-thunk invokes it with dispatch, getState and extraArgument params. Please check its source code, it's really tiny and simple.
Basically it means exactly what Radio said: if it's undefined in pickFolder that's because it was undefined in the caller. Also I don't see any usages of destination in your pickFolder, so maybe check for the typos.
It seems that redux is not happy with not plan javascript object. As shown above, when I tried to dispatch an actionCreator which had a bound function call as a parameter, it was missing when the actionCreator was created.
I also tried to create a reducer that placed a function handle (bound function) into the store, and it was not stored, and the prior value was removed (a placeholder).
I am puzzled by what #Radio- is saying, since what I am seeing is that redux does not like things that are not plain javascript objects (either as parameters to the dispatch call, or as values from the reducer to be placed in the store).

Is it ok to add helper methods to redux store?

I'm making an SVG chart and I have a bunch of helper methods for converting between coordinates and dates. Currently I need to apply scaling everywhere and it's annoying, so I was considering adding the helper methods to the redux store, where the store has access to scaling and can automatically apply it in the methods.
Is this ideal?
I'm also considering creating a function that takes scale, and returns all of the helper methods with the scale curried in. If I do it this way, then I need to reinstantiate this curried function in every file I use it, passing scale each time.
Using redux store I'd only have to do it once.
EDIT: More detail
Restriction: "store" is inaccessible, outside of perhaps middleware.
convert
getDateFromX(x) / scale
to just
getDateFromX(x)
Where scale is built into the function. Like, getDateFromX is always divided by scale, so it should be in the function, but the scale is in the redux store.
I was originally asking if I could have my application reducer return a function in it's returned object "getDateFromX" that could be grabbed through mapStateToProps in connect. I understand it's frowned upon, or I wouldn't have asked the original question, I would have simply implemented this.
Also, there are about 7 more functions that do similar conversions. Converting between hours, days, date, and x.
No. You could technically do that, I guess, but it's definitely not a good use of Redux. (I'm actually having trouble envisioning how "methods attached to the store" would actually fit into things.)
The more idiomatic approach would be to use selector functions. For example:
import {createSelector} from "reselect";
const selectScale = state => state.scale;
const selectSomeValue = state => state.someValue;
const selectScaledValue = createSelector(
selectScale, selectSomeValue,
(scale, somevalue) => scale * someValue
);
If you consistently use selectScaledValue() in your mapStateToProps functions, then it would give you the scaled value every time either the scale or the original value changes.
As our app grows we have been running into similar issues. We try to keep our state as small as possible and then calculate additional information on demand. We've found this to be fairly robust but as the app grows we have to import these state helper functions throughout the app and it's not so user friendly. I've been toying with the idea of taking all the state helpers and attaching them to the state objects in a middleware piece so that components have easy access to them but they aren't actually being stored in our Redux store. I think you could combine markerikson's point but instead of duplicating these functions across your codebase pass them around with the state.
So instead of doing this all over your app
import { getDateFromX } from 'helpers'
...
getDateFromX(state)
You do this:
[ REDUX ] ---> [ CONNECT ] ---> [ UI ]
^
|
Attach helpers here
And then as your state is passed around you can do state.helpers.getDateFromX
This isn't fully fleshed out but I've also been trying to come up with an elegant solution to this issue that doesn't violate best practices of Redux.

What prevents code from changing the store state?

The store has a method called getState that will return the current state of the store.
What prevents code somewhere in my application from (accidentally) modifying the returned state from store?
Let's say i call this:
let state = store.getState();
state.someProperty = 'fun';
The implementation that i've found on getState on the store object simply returns the inner state object that gets overwritten with each new action.
const getState = () => state;
In between actions/new states what prevents code from modifying the state that will be read by another subscriber? In my above example, setting someProperty to 'fun' will persist inside the store on the state property, until overwritten.
While i'm obviously not supposed to modify the state, a simple mistake might bind the state to some component that (unknowingly) modifies its inputs - perhaps on a 2-way binding in an angular environment?
<app-some-component [user]="state"></app-some-component>
Shouldn't getState() be implemented as a clone of its state model?
P.S. This is not specifically related to Angular - which is why i didn't add the tag - to allow more people not used to Angular to answer the question.
The answer is: nothing :)
The core Redux library itself technically doesn't actually care if state gets mutated or not. You could actually mutate in your reducers, or have other parts of your app get the state tree and mutate it, and the store itself wouldn't know or care.
However, mutation will break time-travel debugging, as well as make tests unreliable. Even more importantly, the React-Redux library assumes that you will handle your state immutably, and relies on shallow equality comparisons to see if the state has changed. (This is the reason why "Why isn't my component re-rendering?" is in the Redux FAQ. 99.9% of the time, it's due to accidental mutation.)
If you are concerned about mutation, you can use a library like Immutable.js instead of plain JS objects, or use one of the several tools for freezing your state in development to catch mutations.

Composing higher order reducers in Redux

I've created some factory functions that give me simple (or more advanced) reducers. For example (simple one - base on action type set RequestState constant as a value):
export const reduceRequestState = (requestTypes: RequestActionTypes) =>
(state: RequestState = RequestState.None, action: Action): RequestState => {
switch (action.type) {
case requestTypes.start:
return RequestState.Waiting;
case requestTypes.success:
return RequestState.Success;
case requestTypes.error:
return RequestState.Error;
case requestTypes.reset:
return RequestState.None;
default:
return state;
}
};
Using those factory functions and combineReducers from redux I can compose them into fully functional reducer that handles most of my casual actions. That gives me readable code and prevents me from making silly mistakes.
Factories are good for common actions but when I need to add some custom behavior (for action type) which should modify some part of the store significantly I would like to write a custom part of the reducer that will handle that action for me.
The idea is to compose reducers in an iterate manner, so combineReducers but for an array. This way I could use my factories creating reducer and then combine it with my custom reducer that handles some specific actions. The combineReducers for an array would then call the first one, recognize that nothing has changed and call the second (custom) one to handle the action.
I was looking for some solution and found redux-actions but do not quite like the way it links actions and reducers making the semantics little different from what I'm used to. Maybe I do not get it, but eventually I like to see that my reducer is written as pure function.
I am looking for some hint that will show me the way.
Is there any library or project that uses any kind of higher order reducers and combines them in some way?
Are there any downsides regarding composing reducers like described above?
Yep, since reducers are just functions, there's an infinite number of ways you can organize the logic, and composing multiple functions together is very encouraged.
The "reducers in an array" idea you're looking for is https://github.com/acdlite/reduce-reducers. I use it frequently in my own app for exactly that kind of behavior - running a combineReducers-generated reducer first, then running reducers for more specific behavior in turn.
I've written a section for the Redux docs called Structuring Reducers, which covers a number of topics related to reducer logic. That includes useful patterns beyond the usual combineReducers approach.
I also have a list of many other reducer-related utilities as part of my Redux addons catalog.

Redux - Use action object method in reducer instead of switch

I'm new to redux and looked at redux-actions or using switch statements in reducer, and though I'm not against using a switch statement, I'm wondering, isn't it easier to just use the call the action method?
Here's what I'm thinking
import actions from './actions'
const reducer = (state = {}, action) => {
if (actions[action.type]) return Object.assign({},
state, actions[action.type](action)
);
return state;
}
I've just tested this on my first reducer and action, and it works, but it seems quite obvious so I'm wondering why the switch type is the chosen way?
Switch statements are certainly the most common approach, but lookup tables are common as well. You can even use plain if/then conditions if you want. Ultimately, how you write your reducers is up to you.
FYI, this topic is covered in the Redux FAQ, in the FAQ: Reducers section. You might also want to read the new "Structuring Reducers" how-to section as well.
Some observations:
Don't refer to these external functions as "actions". They're not actions. They're actually reducers themselves.
Being reducers, you really ought to be passing the state object to them. Oftentimes, you'll want/need to utilise information contained in the current state, as well as information contained in the action object.
Otherwise, this seems like an appropriate approach.

Resources