-
Components should be written as function components only. In case they need access to local state and/or side-effects (life cycle methods) Hooks should be used. That is, no ES6 classes anymore.
-
Follow the Container and Presentational design pattern.
-
Only use
index.js
files for exporting modules and don't use them within every folder instead reserve them for root folders such assrc/components
. -
All component props should have type definitions using the
prop-types
library. -
For components, use an arrow function.
-
Destructure props consistently, i.e., pick a way and stick to it.
-
Use the shorthand version of
React.Fragment
, e.g.:<>Contents</>
. -
Use early return in functions. It is easier to read, avoids unnecessary indentation especially when there are several conditions in a row and emphasises the "core" of the function.
Don't do this:
function notUsingEarlyReturn(arg1, arg2) { if (arg1) { const foo = someOtherFunction(arg2); if (foo) { const baz = anotherFunction(foo); return baz; } else { return 'No foo...'; } } else { return 'No arg1...'; } }
Do this:
function usingEarlyReturn(arg1, arg2) { if (!arg1) { return 'No arg1...'; } const foo = someOtherFunction(arg2); if (!foo) { return 'No foo...'; } const baz = anotherFunction(foo); return baz; }
-
Avoid multi-level spreading of component props, e.g.:
<MembershipApp {...{ ...props, heading: 'Heading', content: 'Content', }} />
It makes it less obvious as to what props that component expects. Instead, explicitly declare each individual prop and only spread the remaining props:
<MembershipApp heading="Heading" content="Content" {...props} />
-
For component API's prefer enums over booleans.
- Avoid inline styles.
More to come…
- Are domain agnostic (a good tool for this is Storybook).
- Are unit tested excluding implementation details.
- Are browser tested.
- Are accessible, e.g.:
- Semantic and valid HTML has been used.
- All visual elements have a text representation.
- Is accessible with a keyboard.
- If necassary, WAI-ARIA has been used.
- Avoid using the
node
prop type if children are known ahead of time.
- Avoid bloated third-party frameworks such as Bootstrap and Foundation instead make use of specialised libraries that do one thing and one thing well, e.g., downshift, react-modal, etc.
- Avoid testing implementation details instead focus more on end user concerns.
- For unit tests:
-
Use React Testing Library instead of Enzyme.
-
Test things that actually need testing, e.g., any state changes. Tests such as "should render correctly" are a waste of time.
-
Avoid
toMatchSnapshot()
tests instead use something likesnapshot-diff
. An example:it(`snapshots the difference between 'associatedTextIds' being applied`, () => { expect( snapshotDiff( <Fieldset {...requiredProps}>{children}</Fieldset>, <Fieldset {...requiredProps} associatedTextIds="id1"> {children} </Fieldset> ) ).toMatchSnapshot(); });
-
- For e2e tests avoid brittle selectors such as
class
,id
, element, or any type of attribute selector as these are all implemention details that will change often. Instead, prefer more end user focused selectors such as selecting the text of elements, e.g.:this.submitButton = Selector('button').withText(`Continue`);
- Mock all third-party libraries.