Skip to content

Instantly share code, notes, and snippets.

@helsont
Last active September 19, 2017 19:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helsont/604326492d8b70631076f3375465e005 to your computer and use it in GitHub Desktop.
Save helsont/604326492d8b70631076f3375465e005 to your computer and use it in GitHub Desktop.
The main file (real code) is ActionCreator.js
/**
* A redux object with data on the action being sent
* @param {String} actionType The "type" of the redux action
* @param {Object} data Any data that will passed to the reducer
* @return Object The redux action
*/
const action = (actionType, data) => {
return {
type: actionType,
receivedAt: Date.now(),
data
};
};
const generator = (reducerName) => {
let obj = {};
['default', 'success', 'error']
.map((fnName) => {
switch (fnName) {
case 'default':
obj[fnName] = (data) => action(reducerName, data);
break;
case 'success':
obj[fnName] = (data) => action(`${reducerName}_SUCCESS`, data);
break;
case 'error':
obj[fnName] = (data) => action(`${reducerName}_ERROR`, data);
break;
default:
throw new Error('Invalid function name provided.');
}
});
return obj;
};
const actionCreator = (reducerName, endpoint) => {
let reducer = {
DEFAULT: reducerName,
SUCCESS: `${reducerName}_SUCCESS`,
ERROR: `${reducerName}_ERROR`,
endpoint
};
let reducerActions = generator(reducerName);
let combined = Object.assign(reducer, reducerActions);
return combined;
};
/**
* Example return object:
* {
* "DEFAULT":"REQUEST_GET_TASK",
* "SUCCESS":"REQUEST_GET_TASK_SUCCESS",
* "ERROR":"REQUEST_GET_TASK_ERROR",
* "endpoint":"/cs/tasks",
* default: (data) => {
* type: REQUEST_GET_TASK,
* receivedAt,
* data
* },
* error: (data) => {
* type: REQUEST_GET_TASK_ERROR,
* receivedAt,
* data
* },
* success: (data) => {
* type: REQUEST_GET_TASK_SUCCESS,
* receivedAt,
* data
* }
* }
*/
export default actionCreator;
// Specifiy the name of the reducer default case and the endpoint used for the
// network request.
export const REQUEST_GET_TASKS = actionCreator('REQUEST_GET_TASKS', '/cs/tasks');
export const requestGetTask = (task) => {
return (dispatch) => {
// use the `.default()` method and pass in any extra parameters
// NOTICE: the parameters must be wrapped with an object!
dispatch(REQUEST_GET_TASK.default({ task }));
// a helpful shortcut to get the endpoint for the API call
return Api.get(REQUEST_GET_TASK.endpoint)
.then(response => {
// we use `.success` and pass in the whole response.
dispatch(REQUEST_GET_TASK.success(response));
})
.catch(error => {
// we use `.success` and pass in the whole error.
dispatch(REQUEST_GET_TASK.error(error));
});
};
};
import {
REQUEST_GET_TASK,
} from './../actions/TaskActions';
// use the .SUCCESS shorthand which reads as the string value
// "REQUEST_GET_TASK_SUCCESS"
// Notice that this also fixes bugs when you try to import a constant value
// that isn't defined. Javascript will just use the value "undefined" in the
// case statement and fail silently, making for difficult debugging!
// By hiding the "SUCCESS" string behind an object, if we attempt to access
// a property on "undefined", Javascript will throw an error, making it
// easier to debug bad import errors.
case REQUEST_GET_TASK.SUCCESS: {
// the response in the network request is wrapped "data" parameters.
// in our case, the network request returns:
// {
// "success": true,
// "data": {
// "id": 100,
// ...(other data)
// }
// }
// which is why we use data.data to get the real value being returned.
const task = action.data.data;
return update(state, {
allTasks: {
[task.id]: {
$set: task
}
},
activeTaskId: {
$set: task.id
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment