Open tony-kerz opened 8 years ago
From this comment in July, using redux-thunk and redux-promise together looks like a pretty good pattern:
// Relies on both thunk and promise middleware
createAction('FETCH_SOMETHING', id => {
// Thunk will be handled by thunk middleware
return dispatch => {
// Trigger optimistic update
dispatch({ type: 'FETCH_SOMETHING_BEGIN', body: { id } });
// Promise will be handled by promise middleware
return api.fetch(id);
}
});
thanks @kevana, i can get with that.
it seems like it might be an improvement to have those characteristics in a single piece of middleware, but for now it could qualify as "idiomatic" ;)
i'll leave this open as a placeholder for the idea of converging those middleware, but project owners can feel free to close if they feel this is a sufficient solution.
@kevana, i just tried the strategy outlined above, and the behavior i witnessed was the thunk not being executed.
the following doesn't take i think because createAction
puts the 'thunk' in a payload
field...?
export const setSkill = createAction(
actions.SET_SKILL,
(skill) => {
return (dispatch, getState) => {
dispatch(setSkillBegin(skill))
return getArticlesPromise(skill)
}
}
)
i have however had some luck with something like:
export const setSkill = (skill) => {
return (dispatch, getState) => {
dispatch(setSkillBegin(skill))
dispatch(createAction(actions.SET_SKILL, getArticlesPromise)(skill))
}
}
I don't have a working example, just stumbled across that comment and figured it might be helpful
I do this
// Actions.js
import store from '../store';
import progress from './Progress/actions';
const myActionCreator = async (argument, dispatch = store.dispatch, getState = store.getState) => {
dispatch(progress.start());
const result = await doSomethingAsync();
dispatch(progress.stop());
return {
type: 'MY_ACTION', payload: result
};
}
This way i can call the function with just the argument from the components, but I can also specify them explicitly in my tests.
I don't use redux-actions. I just use plain redux connect() to bind and connect my action creators.
Now that i am trying to render things server-side it looks like my way of importing the store directly is bad because on the serverside i must be able to change it at runtime from one request to another. What's the correct approach here ?
The best way of dealing with this is to use an alternate thunk middleware that looks for the function in payload
. The thunk middleware is only 5 lines of js, trivial to replace. In mine I also dispatch the action with the return value of the thunk, this is great when you combine with promise middleware.
Lately i ended up removing the promised middleware and using just redux-thunk alone. Looks like a thunk can return a promised value and if it does the dispatch() return value itself is a promise that you can await.
const actionCreator (params) => {
return async (dispatch, getState) => { ... }
}
await dispatch(actionCreator({...}))
@davibe then you have an async reducer? I published redux-thunktions middleware that lets you handle this situation elegantly, there are some examples in the readme.
I don't have an async reducer. Just the code i have written above works fine with redux-thunk. Inside that async method i can dispatch other async action but at some point the final actions actually modifying the state will be sync.
I see, but then you'll need boilerplate each time to handle promises rejections etc. It's better to use promise middleware to handle that so you have a consistent and terse way of handling asynchronous payloads.
I am not sure what you mean. I have a "client action creator" that can dispatch success/error depending on the outcome of the api call. I use it in many other actions so I am no really repeating that code.
hi andrew,
redux-thunk facilitates referencing dispatcher and state by automatically providing the
dispatcher
andgetState
methods.how would you recommend gaining similar references using redux-promise?
regards, tony