There are a ton of for doing asynchronous effects in Redux apps. see this as a bad thing, but I love the intellectual curiosity and willingness to explore in the JavaScript community. libraries Some There wasn’t a effects that met my needs, so I ended up making something new. I’ll share the ideas I borrowed from other effects libraries and how they are used in . Redux library redux-funk For some background, there’s a that goes into why you’d want a tool for asynchronous effects in Redux apps. Stack Overflow post Redux Loop—Declarative effects in reducers The example below demonstrates some of the great ideas in Redux Loop. It’s code for a reducer that returns an instruction to increment a counter after a delay: Redux Loop Example The call to the function above can be read as “return the state unchanged and call with arguments [ ]. loop incrementAsync action.delay An advantage of putting async stuff into reducers is that there is now just one place to look when trying to figure out “ ”. Whether an action should be handled synchronously or asynchronously becomes an implementation detail, rather than a decision that effects what part of the app your code lives in. For comparison, with Redux Thunk, async stuff lives in action creators and with Redux Saga async stuff lives in sagas. What does the app do when this action is dispatched? A big rule in Redux is that reducers should be pure. It may initially seem that Redux Loop violates this rule, but all is well. Calling the function does not actually perform any side effect. Instead, returns a data structure representing the next state and effect. This is what makes it really easy to write tests—you can use deep equality checks to see what effects get returned: loop loop Test for a reducer that uses Redux Loop I didn’t use Redux Loop, because I needed to do custom reducer composition, such as delegating to another reducer from within a reducer. This is complicated with Redux Loop, because its effects using . must be passed up the state tree , , , and isLoop getEffect getModel batch The problem is that in reducer composition, we want the child reducers to only have access to part of the state tree, not the whole thing. So when storing effects on (like in Redux Loop), the effect somehow has to make its way to the top of the tree so that the middleware can see it. The alternative is to do an entire tree traversal, looking for effects, which probably isn’t a good idea. I borrowed a solution from Redux Side Effect and describe it in the next section. state Here’s the redux-funk version of the async counter reducer: Reducer using Redux Funk for declarative effects. I explain how is implemented in the next section. call In the code above, the is used to queue up an effect. The effect can be read as “call incrementAsync with action.delay as its first argument.” I use effects of the form . redux-funk adds a array at the top of the state tree to queue up async effects. So to test a reducer that uses redux-funk, you can just check the key: call [incrementAsync, [action.delay]] funks to refer to [func, [arguments…]] funks funks Redux Side Effect— Using the action object Redux Loop code has to sometimes jump through hoops to pass effects up the state tree. avoids those difficulties and has a because of a trick—it uses the object to communicate effects. Redux Side Effect tiny line count action The following code shows how you can add a side effect in a reducer using Redux Side Effect: Redux Side Effect example The Redux Side Effect middleware just checks the effects on the and calls them all with as the first argument. Using is a shortcut: while child reducers get only branches of the entire state tree, is shared across all reducers. action dispatch action action In spite of the elegance of this solution, I ended up not using Redux Side Effect because: The effects are non-declarative. In the example above, the only way to test that the delay is correct is to actually set a delay and compare timestamps. Reducers become dependent on the presence of the method. sideEffect Mutating the action object , which I’d like to avoid if possible. breaks the Redux paradigm redux-funk also uses the trick of storing actions on the object to avoid having to pass effects. But the implementation maintains the purity of reducers. adds the funk to an action, using a as a key: action call(action, funk) symbol Implementation of the function in redux-funk call When using redux-funk, you call on the top-level reducer, which takes the queue of effects from the action and puts them onto the store state. This restores the action to the way it was, and, more importantly, makes the funks available to store consumers. The testing example above used coalesceReducers coalesceEffects. Here’s the implementation of : coalesceEffects Implementation of coalesceFunks From React-Redux —Subscribing to the Store React-Redux contains helpers for using the state to render the UI, which is arguably the most important side effect. Most effects libraries for Redux are middleware, but, instead, React-Redux subscribes to the store and reacts to the current state. Since redux-funk makes effects as part of store state, you can just subscribe to the store and then program with the effects. I made a small helper, for handling effects in a way similar to how Redux Loop does it: runFunks, Helper for working with declarative effects enables the effects described in reducers to actually get called. In the counter example, the function returns a promise for an action. calls the function and holds onto the promise for the action. When the promise resolves, dispatches the action: runFunks runFunks INCREMENT runFunks Reducer using Redux Funk for declarative effects Here’s the implementation of runFunks: Implementation of runFunks You can use redux-funk without , and implement your own logic for handling. That’s one of the advantages of storing effects on For example, you could use a variant of the code above to add delays to every effect, debounce, use callbacks instead of promises, do remote procedure calls, inject dependencies into funks, etc. runFunks state. Try it Out If you’ve made it this far, you’ve seen the entire source code for redux-funk! Hope you get a chance and play with the , which are adapted from the . to try it out examples Redux Saga examples