This is my version of applyMiddleware in use in redux-tiny-router
function compose(...funcs) {
return funcs.reduceRight((composed, f) => f(composed));
}
function is_server() {
return ! (typeof window != 'undefined' && window.document);
}
export function applyMiddleware(...middlewares) {
return (next) => (reducer, initialState) => {
function reducerEnhancer (state,action){
//need to find a way to stick my reducer in here and allow client to call combineReducers
Object.assign(reducer,tinyReducer,reducer);
var res = combineReducers(reducer);
return res(state,action);
}
var store = next(reducerEnhancer, initialState);
middlewares.push(tinyMiddleware);
if (__UNIVERSAL__ && !__CLIENT__){
middlewares.unshift(tinyUniversal);
}
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain, store.dispatch);
var result = {
...store,
dispatch
};
if (__CLIENT__){
init(result);
}
return result;
};
}
it works for adding my custom middleware but i need to add my custom reducer in there too, in my failure to do that, i did this above:
function reducerEnhancer (state,action){
//need to find a way to stick my reducer in here and allow client to call combineReducers
Object.assign(reducer,tinyReducer,reducer);
var res = combineReducers(reducer);
return res(state,action);
}
var store = next(reducerEnhancer, initialState);
so users can't combineReducers, they just pass in the object and my enhancer will combine for them, but i want to allow them to pass the combined reducers and just add on mine, how do i do that?
Can you explain why you want your own applyMiddleware instead of the one that ships with Redux?
It seems that you might be better off exporting middleware and reducer and asking the user to explicitly use them.
@gaearon , I "overload" applyMiddleware to insert the router middleware and to bootstrap the router, you think this should be an separate enhancer? maybe there should be a canonical way of modifying the the redux create store process, just a crazy idea, some wrapper function that receives all functions and its arguments, that have the opportunity to process them?, something like
combineReducers(reducers) returns an object with do() function and its arguments as properties
applyMiddleware(....) the same thing, returns a object with a do() and all arguments as properties
then this wrapper function has access to all the process, one can then modify the arguments and then calls do(...) on each to have the final product, sorta of an more sophisticated compose, but with the intent from the start to be used to modify the creation procedure.
Can you not just instruct the user to include the tinyMiddleware whenever they are creating their store? It doesn't seem to be that unreasonable of an install request. The devtools have you do essentially the same thing, just at a higher level.
@timdorr I was doing this, and it was fine, replacing applyMiddleware is a better choice, as it frees the user to place the middleware at any order, as that has consequences for the router, the thing is replacing applyMiddleware or even combineReducers works fine, and its not too much to ask, i just bring this up as to start a conversation as "patching" core elements as an api does not seems to be a good idea.
Suppose for instance another lib is written that does something else, that also patches applyMiddleware, and combineReducers, now there is a conflict, the user can't use both.
If I were to use rtr( which I'm looking into), I would want there to be no
magic. I'd want to have the same interaction with redux that I already do:
register reducers, add middleware via compose, bind action creators.
Having a reducer modifying the state tree but not being able to see it when
looking at the reducer code is sub optimal imo because now when a new
developer needs to work on the project, they can't "just read the code".
On Thu, Sep 3, 2015 at 1:53 AM Guilherme Guerchmann <
[email protected]> wrote:
@timdorr https://github.com/timdorr I was doing this, and it was fine,
replacing applyMiddleware is a better choice, as it frees the user to place
the middleware at any order, as that has consequences for the router, the
thing is replacing applyMiddleware or even combineReducers works fine, and
its not too much to ask, i just bring this up as to start a conversation as
"patching" core elements as an api does not seems to be a good idea.
Suppose for instance another lib is written that does something else, that
also patches applyMiddleware, and combineReducers, now there is a conflict,
the user can't use both.—
Reply to this email directly or view it on GitHub
https://github.com/rackt/redux/issues/678#issuecomment-137343483.
It's better to export the primitives (middleware, reducer) and give user control over them, than to hide it.
Otherwise every other library will want to “own” applyMiddleware and it'll be a mess.
@gaearon yes, what i am doing now is both, having two choices as to how to bring rtr in, one for convenience, and the other for compatibility. @danmartinez101 There are no shenanigans inside applyMiddleware, its just adding the router middleware. i will do the same to combineReducers, to remove reducerEnhancer.
Most helpful comment
It's better to export the primitives (middleware, reducer) and give user control over them, than to hide it.
Otherwise every other library will want to “own”
applyMiddlewareand it'll be a mess.