Understanding compose functions in redux - redux

I was trying to create a store in redux for which I am currently using following syntax:-
const middlewares = [
thunk,
logger
]
const wlStore = createStore(
rootReducer,
initialState
compose(applyMiddleware(...middlewares))
)
The above works fine for me and I can access the store, but I lately I bumped into another syntax:-
const wlStore=applyMiddleware(thunk,logger)(createStore)(rootReducer)
Both of them seem to be doing the same job.
Is there any reason because of which I should prefer one over another? Pros/Cons?

Improved readability and convenience are the main advantages of using compose.
Compose is used when you want to pass multiple store enhancers to the store. Store enhancers are higher order functions that add some extra functionality to the store. The only store enhancer which is supplied with Redux by default is applyMiddleware however many other are available.
Store Enhancers are Higher Order Functions
What are higher order functions? Paraphrased from the Haskell docs:
Higher order functions can take functions as parameters and return functions as return
values. A function that does either of those is called a higher order
function
From the Redux docs:
All compose does is let you write deeply nested function transformations without the rightward drift of the code. Don’t give it too much credit!
So when we chain our higher order functions (store enhancers) instead of having to write
func1(func2(func3(func4))))
we could just write
compose(func1, func2, func3, func4)
These two lines of code do the same thing. It is only the syntax which differs.
Redux Example
From the Redux docs if we don't use compose we would have
finalCreateStore =
applyMiddleware(middleware)(
require('redux-devtools').devTools()(
require('redux-devtools').persistState(
window.location.href.match(/[?&]debug_session=([^&]+)\b/)
)()
)
)(createStore);
Whereas if we use compose
finalCreateStore = compose(
applyMiddleware(...middleware),
require('redux-devtools').devTools(),
require('redux-devtools').persistState(
window.location.href.match(/[?&]debug_session=([^&]+)\b/)
)
)(createStore);
To read more about Redux's compose function click here

Related

Can a VUE 3 composable contain more than a single exported function?

I am trying to re-write some functions as VUE Composables and it looks to me like only one exported function is available for a single 'composable.ts' file.
Is that true, or is there a way to export multiple functions from a single composable?
The way that composables are (and should be used) is that they are a single function which encapsulates and reuses stateful logic. That being said, you could return multiple functions inside of the composable or even export multiple composables from the same file. An example:
import { useFoo, useBar } from '...'
const { doX, doY } = useFoo();
const { doZ } = useBar();
doX();
doY();
doZ();
If your code could be improved by making the composable stateless and doesn't need to be coupled with Vue after all, you are probably using it for the wrong cause. It would then (depending on the use-case) probably be better to use helper type functions instead.

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.

Should calculations be stored in Redux store if those are to be submitted in a request?

I have a form that asks the user to type in some numbers. Then, some calculations are made using those numbers that are stored in a Redux store. Right now I do not store the calculations in the Redux store, but just do them inside the render function of my component.
Now I need the submitted form to include those calculated values in my HTTP request. How should I go about it? Should I make the Redux store hold the calculations?
If you plan on using the raw values as well as the calculated values in your UI, I can see a benefit to keeping both inside of your redux store.
If you only need to use the calculation when you make the HTTP request, and the calculated data is not being used as a part of the UI, a cleaner implementation might be to separate the function that does the calculation into a utility file, and importing and using the function in the component/container or actions file that the calculation is needed.
I think this would create a clearer separation of concerns in each file, and the calculation utility could be used in multiple files if necessary.
// Utility file
export const calculationFunction = (someParam) => {
\\ Calculation here
return yourAnswer
}
then
// Actions File (Note this is how my action dispatch is set up, yours might look a bit different
import { calculationFunction } from 'utilities/calculations';
export const sendData = (data) => ({
type: types.SEND_DATA,
responseTypes: [types.SEND_DATA_SUCCESS, types.SEND_DATA_FAILURE],
promise: (client: any) => client.post('/data', calculationFunction(data)),
});

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