React clean code, coding style guide, and best practice

Iqbal Novramadani
4 min readOct 29, 2019

Have you ever been frustrated with your code when it grows?

At Forstek we believe in good coding practice to deliver high-quality products.
We have been helping startup founders, small businesses, and established companies by crafting best version of their digital products with some sets of practice. Want to know more? Continue reading.

Photo by Max Duzij on Unsplash

Below is the coding style guide that we follow. Happy reading!

Git

  • Use ~/.gitignore to ignore files related to your environment / editor.
  • Use present tense in commits “upgrade dependencies” or “introduce custom error object”
  • Use [Conventional Commits][conventional-commits-url]:
feat: add hat wobble #227 
^---^ ^------------^ ^--^
| | |
| | +-> Issue number
| |
| +-> Summary in present tense.
|
+-------> Type: chore, docs, feat, fix, refactor, style, or test.

Git naming reference

  • Changes to projects are achieved through issues and pull requests (PRs).
  • Issues are created first to describe the change that is needed (add a new endpoint to an API, fix a bug, refactor a module, cleanup, etc…).
  • Next, a PR is opened to address the issue. Prefix the git branch name with the issue number (e.g. 197-add-get-publisher).
  • Pull request title should state the goal of pull request clearly.
  • Pull request description should describe how the PR will achieve that goal.
  • If PR contains UI changes or additions, please include screenshots or animated gifs showing the change. (e.g. use https://getkap.co/ on OSX)
  • In the description, use the phrase “Closes #XX” (where XX is the issue number).
  • Each PR should be as small and simple as possible to prevent bugs and make code review as quick as possible. Do not include unrelated changes. Open a separate issue/PR for those.
  • When you want specific persons to review your pull request, mention them using @ syntax in the end of the description (e.g. "@iqbalnovramadani, please review.")
  • You may use as many commits as you would like while working on a pull request. However, before it can be merged it must be squashed to a single commit. This commit should have either the issue or PR number added to the end (e.g. “feat: add get publisher endpoint #197”). This way it is easy to find the context for a change in the git log.

Library

  • Utility: JavaScript ES6 + Lodash
  • Styling: Styled Components + CSS Modules
  • Asynchronous Requests: axios
  • Formatting: StandardJS
  • Type Checking: PropTypes
  • State Management: React’s local state and Redux (with Redux-Thunk and Redux-Saga)
  • Routing: React Router
  • UI Components: React-bootstrap
  • Internationalization: React-Intl
  • Time: moment.js
  • Testing: Jest with Enzyme, Cypress

Project structure

Below is the guideline for project structure.

.babelrc
.env
cypress.json
doczrc.js
package.json
package-lock.json
README.md
/node_modules
/public
/cypress
utils.js (all testing helper functions here)
/examples (all example generated code from cypress put here)
/fixtures
/integration (test suites here)
/plugins
/support
/src
/api
request.js (axios wrapper for easy api call)
user.js
page.js
...
/assets
/images
/components (all stateless components goes here)
/Button
Button.mdx (documentation)
StyledComponents (component styling)
index.js
Button.test (jest/enzyme test)
/Input
/...
/constants
/messages (all paragraph, dialog, popup, or toast message for users (separate per language))
ar.js
en.js
id.js
/labels (all text in button, dropdown, etc (separate per language))
ar.js
en.js
id.js
/containers (all stateful components goes here)
/Homepage
index.js
reducer.js
selector.js (redux selector e.g. using reselect)
actions.js
constants.js (constants for redux actions)
/components
/Sidenav (follow above pattern for components)
Sidenav.mdx
StyledComponents
index.js
Sidenav.test (jest/enzyme test)
/components
/...
/...
/utils
history.js (createBrowserHistory)
index.js (all helper functions goes here)
/styles
index.css (don't style without specific classname here!)
globalReducer.js
index.js (entry point)
store.js (Redux store)



// next.js project
project
components
containers
pages
... follow above pattern

Code style

We use StandardJs to maintain code style and consistency and avoid style arguments. npm start should also run standard so that it will fail to start when style does not meet the requirements.

Other style points:

  • Code should be simple and explicit.
  • Callbacks are preferred over Promises.
  • Functional style is preferred to OOP.
  • Prefer small modules that do one thing well and avoid large frameworks.
  • If a module exports a single function use module.exports = ... not module.exports.thing = ....
  • Line length should be limited to 80 characters.
  • When writing a module use this order:
  • External dependencies (e.g. import qs from 'query-string')
  • Internal dependencies (e.g. import api from './api')
  • Any declarations or actions absolutely needed before module.exports
  • module.exports
  • Everything else should be ordered “high-level” to “low-level” and “first-use” to “last-use” — low-level helper functions should be at the bottom.
  • Use descriptive variable names.
  • Code and comments should stay within 80 character line length.
  • Prefer .forEach() over for loops.
  • Default name for a callback is cb.
  • Functions should generally not accept more than 3–4 arguments, consider using an “options” object instead.
  • Use single line conditionals when possible.
  • Use early returns when possible.
  • Give upper most declarations (usually object destructuring and local vars) separate new line
  • Give if expression / conditional expression separate new line
  • Use fat arrow function assigned to class property instead of common function for UI Component methods
  • Don’t bind function on render method and use inline style, bad for performance
  • Sort constants, props alphabetically, wherever possible
  • Sort value props then handler props
  • Embed “on” in front of handler props name to distinguish it with value props
  • Embed “is”/”has”/”should” for boolean variable/props
  • When stateless component has a lot of props, destructure props inside the function
  • Gather all related functions close, with called functions below the function which is calling them
  • Called functions should be declared in correct order as called

Need clear code samples? Sure, have a look here:
https://gist.github.com/inovramadani/c1b17f2534a8b8d441f6ba8ac80296ae

If you have best practice that is not covered here or even disagree with one, please share on comments.

Thank you for reading!

--

--

Iqbal Novramadani

Muslim, servant of humanity, business and technology enthusiast. Discuss with me anything about Islam! and maybe software. :)