injectable middlewares, with typed hook #3252
Replies: 4 comments 9 replies
-
I've now changed the API and management logic to much more closely resemble export const dynamicInstance = createDynamicMiddleware();
export const startAppMiddleware = dynamicInstance.startMiddleware as TypedStartMiddleware<
RootState,
AppDispatch
>;
export const stopAppMiddleware = dynamicInstance.stopMiddleware as TypedStopMiddleware<
RootState,
AppDispatch
>;
export const addAppMiddleware = addMiddleware as TypedAddMiddleware<
RootState,
AppDispatch
>;
export const removeAppMiddleware = removeMiddleware as TypedRemoveMiddleware<
RootState,
AppDispatch
>;
export default dynamicInstance.middleware; the main challenge is to try and get a version of dispatch that knows about any injected middlewares, which is why i thought it could be useful if dispatching addMiddleware returned a pre-typed dispatch wrapper (with an attached method to remove the injected middleware) const mwAwareDispatch = dispatch(addMiddleware(middleware1, middleware2));
mwAwareDispatch(action(payload));
mwAwareDispatch.remove(); the hook would still be preferable in the context of a component of course, but that's not always available (and i'm not 100% sold on the logic inside that hook yet) const dispatch = useMiddlewareDispatch(middleware1, middleware2); using the map entry style from createListenerMiddleware, it's no longer a concern if the same middleware is injected twice - if it's the same function reference it'll use the same entry. |
Beta Was this translation helpful? Give feedback.
-
Some ideas.
export const addAppMiddleware = addMiddleware.withTypes<RootState, AppDispatch>();
// or, for consistency:
export const addAppMiddleware = addMiddleware.withTypes<{ state: RootState, dispatch: AppDispatch}>();
// in another file
export const useDispatchWithExtraMw = dispatchHookWithMiddleware(middleware1, middleware2)
//in the component
const dispatch = useDispatchWithExtraMw (); That would keep the middleware itself out of the component file, and we could already inject when |
Beta Was this translation helpful? Give feedback.
-
I've opened #3256 for a proper place to store the lib code, and updated the CSB to include some actual (if contrived) example of lazy loading components/middleware. :) |
Beta Was this translation helpful? Give feedback.
-
wonder if it's worth scoping the withMiddleware action to the instance (with an ID or something) - it might be desireable to have multiple dynamicMiddleware instances (e.g. one before all static middlewares, and one after) |
Beta Was this translation helpful? Give feedback.
-
playing around with some ideas based on redux-dynamic-middlewares and createListenerMiddleware
typically the issue with injectable middlewares is that the dispatch typing is unaware of them, so i thought a custom
useDispatch
-style hook returning a dispatch that's aware of the middlewares it's injected could be usefulcodesandbox here
so far i've just reused redux-dynamic-middlewares' logic for managing injected middleware - there's nothing to prevent the same middleware being injected twice, etc. i did however change it so that you dispatch an action to add middleware, instead of exporting methods on an instance (as i wasn't entirely keen on the fact that
createDynamicMiddlewares
assumes you'll use the instance with only one store)edit:
i've now adapted it to use the same logic createListenerMiddleware uses to manage its listeners - each middleware entry has a map of MiddlewareAPI to the applied version of that middleware, to avoid doing it every dispatch
Beta Was this translation helpful? Give feedback.
All reactions