From 60626b828bccc727f5dacd78925659523b572cff Mon Sep 17 00:00:00 2001 From: Ryan Quey Date: Tue, 26 Sep 2017 10:00:25 -0700 Subject: [PATCH] Update README.md --- README.md | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/README.md b/README.md index bf37667..8a7f3fb 100644 --- a/README.md +++ b/README.md @@ -91,3 +91,97 @@ User interface design (UI) is used to describe graphical or aesthetic changes th #### Reasons for UX / UI breakdown Good design is not focused only on mechanics or function, and good design is not focused entirely on what is the most aesthetically pleasing, and good design is not focusing on mechanics and aesthetics at the same time. Good design is focusing on mechanics and aesthetics separately, at different times, but giving them equal attention. This doesn't mean that in some way that can't drive one another, it just means that they are different things and what looks good won't always keep users, and what works well doesn't always draw in users, both areas must be addressed. + +# Redux conventions + +## Actions + +### Action naming +* CREATE, FETCH, UPDATE, DESTROY/ARCHIVE are your crud actions (although DESTROY will sometimes archive) +* Name the crud actions using the singular + +* The constants for the actions will be [verb] _ [noun] because it sounds good +* The functions that call the actions (imported from action/index.js) will be [verb][noun], in camel case, for the sake of consistency + +* The main disadvantage of putting of the a verb first is that actions can quickly become disorganized, causing developers to potentially create actions that replicate already existing actions. This is bad. Therefore, make sure to organize actions according to the noun. + +The right way: (in the actions/types.js file) +``` + CREATE_ORGANIZATION: 'CREATE_ORGANIZATION', + UPDATE_ORGANIZATION: 'UPDATE_ORGANIZATION', + RETRIEVE_ORGANIZATION: 'RETRIEVE_ORGANIZATION' +``` + +The wrong way: +``` + RETRIEVE_ORGANIZATION: 'RETRIEVE_ORGANIZATION', + RETRIEVE_USERS: 'RETRIEVE_USERS' +``` +This way, if someone wants to fetch organizations, they won't accidentally do a search for "fetch" or "get", not see anything, and then create a new action "FETCH_ORGANIZATION" + + +### Action wrappers (aka, how to do asynchronous stuff) +In order to avoid dispatching unnecessary actions and to avoid unnecessary complexity, we are not going to use redux sagas or thunk. Instead, we will simply wrap our redux actions in a function, eg, + +``` +//in admin/actions/organizationActions.js +import adminActionTypes from 'admin/actions/types' +import sharedActionTypes from 'shared/actions/types' + +export const createOrganization (payload) => { + new Promise((resolve, reject) => { + axios.post("/organizations", payload) + }) + .then((response) => { + store.dispatch({ + type: adminActionTypes.CREATE_ORGANIZATION, + payload: response + }) + }) + .catch((err) => { + //probably handle errors a little differently, but this is just an example + store.dispatch({ + type: sharedActionTypes.HANDLE_ERROR, + payload: err + }) + }) +} + +//in admin/components/partials/NewOrganization.js +import { organizationActions } from 'admin/actions' + +... +handleSubmit (e, newOrganization) { + e.preventDefault() + organizationActions.createOrganization(newOrganization) +} + +render ... +``` + +I like to call these functions that wrap the actions "action functions". +As the example above shows, rather than dispatching actions from a component, a component will import all of the action functions it needs, and simply call the function. + +### Handling callbacks +Often, components will need to respond to the result of asynchronous actions. + +Rather than having the action function returning a promise to the component, or even passing a call back to the action function from the component, we will keep our code clean and organized by only communicating with the component via actions. As the above example shows, even errors are handled through dispatching actions. + +``` +... + .catch((err) => { + //probably handle errors a little differently, but this is just an example + store.dispatch({ + type: sharedActionTypes.HANDLE_ERROR, + payload: err + }) + }) +... +``` +If a component needs to respond to this error, it should receive this error from props by subscribing via mapStateToProps. `this.componentWillReceiveProps` will often come in handy to respond to changes in the store. + + +Summary: +* Action constants and functions should be named verb first ("createUserForLine") +* Wrap actions in functions +* Even redux actions that do not require any asynchronous code should still be wrapped in functions, for consistency and organization