I currently am using action creators with Redux to dispatch user actions (for example, fetching account information). These action creators return promises from an API request that, when they resolve, update the store.
The issue I'm having is that I want to "intercept" certain responses from the API, in my case, an invalid JWT token. In such cases, I want to preserve the pending promise, prompt a Login modal, and if the login is successful, refetch and resolve the promise.
It's sufficient for me to check the response after I call fetch
this way:
Root.js - Put Modal component in the DOM
export default (props) => {
return (
<div>
<Modal />
<App />
</div>
)
}
Modal.js - handle different modal types (approach adopted from this post)
const MODALS = {
LOGIN: LoginModal
}
const ModalRoot = ({type, props}) => {
if (!MODALS[type]) return null;
return <Modal {...props} />;
}
export default connect(
state => state.modal
)(ModalRoot);
reducer.js - Modal reducer
const initialState = {type: null, props: {}}
export default function modal(state = initialState, action) {
switch (action.type) {
case 'SHOW_MODAL':
return Object.assign({}, state, {
type: action.modalType,
props: {...action.props}
});
case 'HIDE_MODAL':
return initialState;
default:
return state;
}
}
actions.js - return promise to fetch call
const promptLogin = () => (dispatch, getState) => {
return new Promise((resolve, reject) => {
return dispatch(showModal('LOGIN', {
successCallback: (user) => resolve(user)
}));
})
}
makeAPIRequest.js - make API call, handle invalid token
fetch(endpoint, requestConfig)
.then(res => res.json())
.then(data => {
/** Invalid JWT Token */
if (data && data.error_code === 403) {
return store.dispatch(promptLogin())
.then(token => {
return makeRequest(method, endpoint, headers, body)
});
}
return data;
});
This problem with this approach is that I'm persisting a callback function (in order to complete the initial request) to the store, which is discouraged in the redux docs.
If my Modal component isn't connected to my fetch logic, and I can't store a Promise or a callback in the state (because they aren't serializable), how can I continue a promise from an initial request after the user performs a login from the modal?