An opinioned coding guideline for React + Redux project @WORD UP
- Use dash to combine words for both file and folder name
components/user-feedbacks.jslib/api-parser.js
- Lowercase. Separated by single dash
nav-bar-item
- However,
__&--is still fine if using BEM style.- eg:
.block__elem--mod
- eg:
|- pages/ -> direct handler for each route
|- account/
|- __test__/
|- index.js
|- styles.scss
|- containers/ -> connect to store
|- personal-info/
|- __test__/
|- index.js
|- styles.scss
|- components/
|- personal-info/
|- __test__/
|- index.js
|- styles.scss
|- reducers/
|- user/
|- __test__/
|- actions.js
|- constants.js
|- reducer.js
|- selector.js
|- styles/ -> common css like variable, mixin..
|- utils/ -> helper function
- Use 2 spaces for indentation instead of
tab
- Use backslash
// comments when necessary - For todos use the format
//TODO: (with the person responsible and reason)- for example:
//TODO: (From Mark) hookup Ajax to rest server
- for example:
- Organize props by category.
<Input ref={(ref) => (this.BTN = ref)} onBlur={this.handleBlur} onChange={this.handleChange} height={height} width={width} />
-
In order to understand where's the code comes from, group all of
importstatements logically// group 1: import javascript native or 3rd libraries import React; import moment; // group 2: import modules like utilities, actions, reducers ... import { fetchCourseById } from 'Utils/apis/admin'; import { toRoute } from 'Utils/route-handler'; // group 3: import components import Loader from 'Components/generic-tools/loader'; import ProductList from 'Components/product-list'; // group 4: import css, styles, class import classnames from 'classnames/bind'; import styles from './styles.scss';
- should prevent using too many props in single component
- use proper naming (reference)
Array – use plural nouns. e.g. items Number – use prefix num or postfix count, index etc that can imply a number. e.g. numItems, itemCount, itemIndex Bool – use prefix is, can, has is: for visual/behavior variations. e.g. isVisible, isEnable, isActive can: fore behavior variations or conditional visual variations. e.g. canToggle, canExpand, canHaveCancelButton has: for toggling UI elements. e.g. hasCancelButton, hasHeader Object – use noun. e.g. item Node – use prefix node. containerNode Element – use prefix element. hoverElement
- A giant reducer is hard to understand and also usually implies it has too many responsibilities. Having a smaller reducer also helps to make its corresponding actions smaller and more focued.
- We can use redux built in
#combineReducersor redux-immutable package - Refactoring Reducers Example
- Using combineReducers
- A container prepares data from store and dispatch actions and connected them to its component.
-
user-info-selector.jsmay provides#get_full_name,#get_last_ordermethods which talk to Store. -
Can also provides some reusable mutation functions.
-
An example of using reusable state-mutation functions:
// utils.js const applyFn = (state, fn) => fn(state); export const pipe = (fns, state) => state.withMutations((s) => fns.reduce(applyFn, s)); // reducer.js return pipe( [mutate.closeModal, mutate.stopLoading, mutate.updateLoan(action.loan)], state );
-
- No duplicated data in different entries. If there are multiple entities need to refer to the same data, use foreign key like in a database.
- It's hard and error-prone to get/update data in a nested object. In addition, update data with a deep level will make several parent nodes being updated which may results in unnecessary render.
- Use normalizr if needed.
- Normalizing State Shape
- Instead of using
state.set('key1', value1).set('key2', 'value2'), usewithMutationsto wrap multiple actions into one update. Since Immutable.js will perform re-arranging in all the processes and retain all intermediate states. - eg:
state.withMutations(s => s.set('key1', value1).set('key2', 'value2'))
- It's a resource demanding action and also we lose the performance benefit. In addition, every
toJS()call results in a new object which will always trigger unnecessary render.
'a string'`a string with ${variable}`
- The line of codes will be significantly lesser
- Duplicated codes are easy to be identified. Though some codes are not the same, but actually doing similar tasks. In that case, think if they should be combined into a component or a module class.
- like
document.addEventlistener.- Since we're in a SPA, remember to remove the listener at a proper timing like
componentDidUnmount. - Take the parent/child tree into account. Don't add the same listener at both parents and children.
- Since we're in a SPA, remember to remove the listener at a proper timing like
apply eslint-config-airbnb with plugin react and prettier