Reputation: 23
I'm trying to wrap my head around Redux or state management in general for the front-end applications.
As far as I know, there are three basic libraries to create complex actions logic: redux-thunk
, redux-saga
and redux-observable
.
I'm using redux-thunk
to create a chain of the async operations, but I found them a little bit inappropriate: action creators should create actions, not functions.
In order to get around this, I've created actions (simple action creators) and operations (thunks) with redux-toolkit
, but I still see them a little bit confusing:
export function add(state, action) { ... }
export function added(state, action) { ... }
export function addItem(payload) {
return async (dispatch) => {
dispatch(actions.add(payload))
const { data } = await Items.create(action.payload);
dispatch(actions.added(payload))
}
}
It looks ok, but I can see myself trying to dispatch add
directly in the future.
Using redux-saga
seems unnatural thanks to the generator syntax. I don't have to say anything about redux-observable
, it's over-complicated for this simple task.
So I tried to use simple custom middleware for this kind of work, but I don't really know if it's a "good practice" or "bad practice". However, it allows to use simple actions to fire an observer that dispatches matching function:
let listeners = {}
export const observer = store => next => action => {
const result = next(action)
if (action.type in listeners) {
listeners[action.type](store.dispatch, action)
}
return result
}
export const createListener = (action, listener) => {
listeners[action.type] = listener
}
Code above allows to write "observers" / "listeners" like below:
createListener(actions.add, async (dispatch, action) => {
const { data } = await Items.create(action.payload)
dispatch(actions.added(data))
})
...which allows to dispatch callback attached to the listened actions. Looks very simple and clean for me.
Is this a bad way to solve this problem?
Upvotes: 1
Views: 905
Reputation: 67499
I'm a Redux maintainer and creator of Redux Toolkit.
Thunks exist to allow you to move complex synchronous and semi-complex async logic outside of components. Components typically use action creators to avoid knowing the details of how to define a given action object. Thunk action creators exist to provide parallel syntax, allowing components to kick off logic without needing to know the details of whether it's a simple action dispatch or something more complex.
That said, thunks do not give you a way to respond to dispatched actions, because the only thing the thunk middleware does is look to see if you've passed a thunk function to dispatch
, and if so, call it. Sagas and observables both provide APIs that let you run additional logic in response to dispatched actions. See the Redux FAQ entry on "how do I choose between thunks, sagas, and observables?" for more details.
The middleware you've just shown there is a typical example of a simple "action listener" middleware - really a much simpler version of what sagas and observables let you do. In fact, we're hoping to add a similar middleware to Redux Toolkit, but haven't done so yet.
So, yes, the middleware itself is a valid tool to create, but you haven't provided sufficient information on what specific problem you're trying to solve, so I can't say whether it's an appropriate tool for your problem.
Upvotes: 3