Standardize your React development with these key decisions
React was open-sourced in 2013. Since then, it has evolved. As you search the web, you’ll stumble across old posts with dated approaches. So, here are eight key decisions your team needs to make when writing React components today.
Decision 1: Dev Environment
Before you write your first component, your team needs to agree on a dev environment. Lots of options…
Sure, you can build a JS dev environment from scratch. 25% of React devs do just that. My current team uses a fork of create-react-app with additional features such as a realistic mock API that supports CRUD, a reusable component library, and linting enhancements (we lint our test files too, which create-react-app ignores). I enjoy create-react-app, but this tool will help you compare many compelling alternatives. Want to render on the server? Check out Gatsby or Next.js. You can even consider using an online editor like CodeSandbox.
Decision 2: Types
You can ignore types, use prop-types, use Flow, or use TypeScript. Note that prop-types was extracted to a separate library in React 15.5, so older posts will show imports that don’t work anymore.
The community remains divided on this topic:
I prefer prop-types because I find it provides sufficient type safety in React components with little friction. Using the combination of Babel, Jest tests, ESLint, and prop-types, I rarely see runtime type issues.
Decision 3: createClass vs ES Class
React.createClass was the original API, but in 15.5, it was deprecated. Some feel we jumped the gun moving to ES classes. Regardless, the createClass style has been moved out of React core and relegated to a single page called “React without ES6” in the React docs. So it’s clear: ES classes are the future. You can easily convert from createClass to ES Classes using react-codemod.
Decision 4: Class vs Functional
You can declare React components via a class or a function. Classes are useful when you need refs, and lifecycle methods. Here are 9 reasons to consider using functions when possible. But it’s also worth noting that there are some downsides to functional components.
Decision 5: State
You can use plain React component state. It’s sufficient. Lifting state scales nicely. Or, you may enjoy Redux or MobX:
I’m a fan of Redux, but I often use plain React since it’s simpler. In my current role, we’ve shipped about a dozen React apps, and decided Redux was worth it for two. I prefer shipping many, small, autonomous apps over a single large app.
On a related note, if you’re interested in immutable state, there are at least 4 ways to keep your state immutable.
Decision 6: Binding
There are at least half a dozen ways you can handle binding in React components. In React’s defense, this is mostly because modern JS offers many ways to handle binding. You can bind in the constructor, bind in render, use an arrow function in render, use a class property, or use decorators. See the comments on this post for even more options! Each approach has its merits, but assuming you’re comfortable with experimental features, I suggest using class properties (aka property initializers) by default today.
This poll is from Aug 2016. Since then, it appears class properties have grown in popularity, and createClass has reduced in popularity.
Side note: Many are confused about why arrow functions and bind in render are potentially problematic. The real reason? It makes shouldComponentUpdate and PureComponent cranky.
Decision 7: Styling
Here’s where the options get seriously intense. There are 50+ ways to style your components including React’s inline styles, traditional CSS, Sass/Less, CSS Modules, and 56 CSS-in-JS options. Not kidding. I explore React styling approaches in detail in the styling module of this course, but here’s the summary:
See why there is so much fragmentation in React’s styling options? There’s no clear winner.
My current team uses Sass with BEM and are happy enough, but I also enjoy styled-components.
Decision 8: Reusable Logic
React initially embraced mixins as a mechanism for sharing code between components. But mixins caused issues and are now considered harmful. You can’t use mixins with ES class components, so now people utilize higher-order components and render props (aka function as child) to share code between components.
Higher-order components are currently more popular, but I prefer render props since they’re often easier to read and create. Michael Jackson recently sold me with this:
And that’s not all…
There are more decisions:
- Will you use a .js or .jsx extension?
- Will you place each component in its own folder?
- Will you enforce one component per file? Will you drive people nuts by slapping an index.js file in each directory?
- If you use propTypes, will you declare them at the bottom, or within the class itself using static properties? Will you declare propTypes as deeply as possible?
- Will you initialize state traditionally in the constructor or utilize the property initializer syntax?
Choose a Standard, Then Automate Enforcement
And all this up, and there are dozens of combinations you may see in the wild today.
So, these next steps are key:
1. Discuss these decisions as a team and document your standard.
2. Don’t waste time manually policing inconsistency in code reviews. Enforce your standards using tools like ESLint, eslint-plugin-react, and prettier.
3. Need to restructure existing React components? Use react-codemod to automate the process.
Other key decisions I’ve overlooked? Chime in via the comments.
Looking for More on React? ⚛️