Last active
October 29, 2018 10:20
-
-
Save artalar/f99c5bd7ef96553286c060785104b215 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const getAsyncType = (type, status) => `${type}_${status}`; | |
| let index = 0; | |
| export const getMasterActionCreator = description => { | |
| const type = `${index++}__${description}`; | |
| const reqType = getAsyncType(type, "REQUEST"); | |
| const respType = getAsyncType(type, "SUCCESS"); | |
| const errType = getAsyncType(type, "ERROR"); | |
| const masterActionCreator = (...params) => ({ params, type }); | |
| masterActionCreator.toString = () => type; | |
| masterActionCreator.request = (...params) => ({ params, type: reqType }); | |
| masterActionCreator.request.toString = () => reqType; | |
| masterActionCreator.response = (...params) => ({ params, type: respType }); | |
| masterActionCreator.response.toString = () => respType; | |
| masterActionCreator.error = (...params) => ({ params, type: errType }); | |
| masterActionCreator.error.toString = () => errType; | |
| return masterActionCreator; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export const createReducer = (handlers, initialState = {}) => ( | |
| state = initialState, | |
| action | |
| ) => | |
| handlers.hasOwnProperty(action.type) | |
| ? handlers[action.type](state, ...action.params) | |
| : state; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // handle middleware | |
| export const handleWorkflow = workflow => store => next => action => { | |
| next(action); | |
| if (workflow.hasOwnProperty(action.type)) { | |
| workflow[action](store, ...action.params); | |
| } | |
| }; | |
| export const createAsyncWorkflow = ( | |
| action, | |
| onRequest, | |
| onAction, | |
| onResponse, | |
| onError | |
| ) => ({ | |
| [action]: (store, ...params) => | |
| onAction | |
| ? store.dispatch(action.request(onAction(store, ...params))) | |
| : store.dispatch(action.request(...params)), | |
| [action.request]: async (store, ...params) => { | |
| try { | |
| const response = await onRequest(...params); | |
| onResponse | |
| ? store.dispatch(action.response(onResponse(store, response))) | |
| : store.dispatch(action.response(response)); | |
| } catch (error) { | |
| onError | |
| ? store.dispatch(action.error(onError(store, error))) | |
| : store.dispatch(action.error(error)); | |
| } | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // actions.js | |
| export const changeField = getMasterActionCreator("CHANGE_FIELD"); | |
| export const sendForm = getMasterActionCreator("SEND_FORM"); | |
| // reducer.js | |
| const initialsState = { | |
| loading: false, | |
| values: localStorage.getItem("form") | {} | |
| }; | |
| export const formReducer = createReducer( | |
| { | |
| [changeField]: (state, name, value) => ({ | |
| ...state, | |
| values: { ...values, [name]: value } | |
| }), | |
| [sendForm.request]: state => ({ ...state, loading: true }), | |
| [sendForm.response]: state => ({ ...state, loading: false }), | |
| [sendForm.error]: state => ({ ...state, loading: false }) | |
| }, | |
| initialsState | |
| ); | |
| // component.js | |
| function handleChange(event) { | |
| this.props.dispatch(changeField(event.target.name, event.target.value)); | |
| } | |
| function handleSubmit(event) { | |
| event.preventDefault(); | |
| this.props.dispatch(sendForm()); | |
| } | |
| // workflow.js | |
| const workflow = { | |
| [changeField]: (store, name, value) => { | |
| /* debounced */ saveToLocalStorage("form", { name, value }); | |
| }, | |
| ...createAsyncWorkflow( | |
| sendForm, // action | |
| formValues => api.sendForm(formValues), // request | |
| store => store.getState().form.values, // prepare payload for request action | |
| // <- paste here prepare payload for response action | |
| // <- paste here prepare payload for error action | |
| ) | |
| }; | |
| export const workflowMidleware = handleWorkflow(workflow); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // actions.js | |
| const CHANGE_FIELD = "CHANGE_FIELD"; | |
| const SEND_FORM_REQUEST = "SEND_FORM_REQUEST"; | |
| const SEND_FORM_RESPONSE = "SEND_FORM_RESPONSE"; | |
| const SEND_FORM_ERROR = "SEND_FORM_ERROR"; | |
| export const changeField = payload => { | |
| /* debounced */ saveToLocalStorage("form", { name, value }); | |
| return { type: CHANGE_FIELD, payload }; | |
| }; | |
| /* | |
| !you still need redux-thunk for this! | |
| */ | |
| export const sendForm = () => async (dispatch, getState) => { | |
| try { | |
| dispatch({ type: SEND_FORM_REQUEST }); | |
| const response = api.sendForm(getState().form.values); | |
| dispatch({ type: SEND_FORM_RESPONSE, payload: response }); | |
| } catch (error) { | |
| dispatch({ type: SEND_FORM_ERROR, payload: response }); | |
| } | |
| }; | |
| // reducer.js | |
| const initialsState = { | |
| loading: false, | |
| values: localStorage.getItem("form") | {} | |
| }; | |
| export const formReducer = (state = initialsState, action) => { | |
| switch (action.type) { | |
| case CHANGE_FIELD: { | |
| const { name, value } = actions.payload; | |
| return { | |
| ...state, | |
| values: { ...values, [name]: value } | |
| }; | |
| } | |
| case SEND_FORM_REQUEST: | |
| return { ...state, loading: true }; | |
| case SEND_FORM_RESPONSE: | |
| return { ...state, loading: false }; | |
| case SEND_FORM_ERROR: | |
| return { ...state, loading: false }; | |
| default: | |
| return state; | |
| } | |
| }; | |
| // component.js | |
| function handleChange(event) { | |
| this.props.dispatch(changeField(event.target.name, event.target.value)); | |
| } | |
| function handleSubmit(event) { | |
| event.preventDefault(); | |
| this.props.dispatch(sendForm()); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment