At blvd, we use React a lot. It's one of the most-used Javascript frameworks in the world, with an extensive community support and library ecosystem. We like it better than Angular, but we're not your parents. Go absolutely wild.
While tools like create-react-app
can be useful, its out-of-the-box
configuration can be a bit limiting, and ejecting kind of defeats its purpose.
You should prioritise setting up your own development tool for your specific stack. We recommend the following libraries:
Personally, we prefer webpack over Parcel due to its ecosystem support. Compared to previous versions, webpack 4 has a significantly reduced initial setup time + config file size. For an example minimal webpack 4 setup for React, see mvws.
Use Visual Studio Code. It has first-class support for JavaScript and TypeScript, complete with code-aware statement completion, Emmet integration for JSX elements, as well top-notch debugging environment.
Any other IDE should do, as long as it supports the Language Server Protocol. If you prefer Atom, you should install the Atom IDE package.
The following style guide should be seen as an extension to the airbnb react style guide. All of the rules listed within should be followed as closely as possible, with exceptions listed below.
To meet the TypeScript styleguide regarding class properties, all React
component lifecycles (including static
lifecycles like
getDerivedStateFromProps
) shall be set to public
.
If declaring a stateless component, you should avoid declaring them as a function
.
// Bad example
function Component({ children }) {
return <div>{children}</div>;
}
// Good example
const Component = ({ children }) => (
<div>{children}</div>
)
Any JS/TS files with a JSX syntax should always be marked as such.
Note that using
.js
for JSX files will also give problems for Emmet autocompletion on VS Code, see Microsoft/vscode#4962.
If declaring an internal class method, you should always prefix it with private
.
This is an extension to the blvd typescript styleguide, where class methods should always be marked either
public
,private
, orprotected
.
Don't use .bind(this)
when binding functions to component context! This can
(and should) be replaced by ES6 arrow functions.
// Bad example
class FancyButton extends React.Component {
handleClick(e) {
e.preventDefault()
}
render() {
return (
<button onClick={this.handleClick.bind(this)}>Click me!</button>
);
}
}
// Bad example
class FancyButton extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick(e) {
e.preventDefault()
}
render() {
return (
<button onClick={this.handleClick}>Click me!</button>
)
}
}
// Good example
class FancyButton extends React.Component {
handleClick(e) {
e.preventDefault()
}
render() {
return (
<button onClick={(e) => this.handleClick(e)}>Click me!</button>
)
}
}
Another alternative to the above example would be converting the handleClick
call into an arrow function, which is commonly used for event handlers, e.g.
class FancyButton extends React.Component {
handleClick = (e) => {
e.preventDefault()
}
render() {
return (
<button onClick={this.handleClick}>Click me!</button>
)
}
}
Note that arrow functions used to come with its own performance pitfalls, even though newer browsers have balanced things out. But still, your mileage may vary.
If using a component with render props, prefer to use a children-based render prop.
class FancierButton extends React.Component {
render() {
return (
<Fragment>
{/* Not so good */}
<LayoutContainer
render={({ theme, setTheme }) => (
<div>
<CurrentTheme>Current theme: {theme}</CurrentTheme>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Switch theme
</button>
</div>
)}
/>
{/* Better */}
<LayoutContainer>
{({ theme, setTheme }) => (
<div>
<CurrentTheme>Current theme: {theme}</CurrentTheme>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Switch theme
</button>
</div>
)}
</LayoutContainer>
</Fragment>
)
}
}
Multiline self-closing tags are less-readable, especially when a render prop extends 10 or so lines, the closing tags can get lost down there. A weird analogy is to imagine the starting and closing tags as airports. An ideal trip on an airplane would end on the runway of another airport and not at, like, a wall.
Instead of defining prop types inline, you should declare them separately.
// Bad example
const App: React.SFC<{ message: string }> = ({ message }) => <div>{message}</div>
// Good example
type AppProps = {
message: string
}
const App: React.SFC<AppProps> = ({ message }) => <div>{message}</div>
This improves code reusability and organization.
- Consider using
type
s for your components' props/states. - Use
interface
s only when your props/state declaration is also a public API definition.
For reference, see sw-yx/react-typescript-cheatsheet § Types or Interfaces?
The tslint.json file provided imports the blvd typescript style guide into TSLint. To use them, include the following packages.
A .prettierrc
is also included for those who use Prettier.
Prettier is a code formatter which ensures your code is formatted to a
consistent style. It works alongside your IDEs and linters, and our
ESLint/TSLint configs works alongside them.
yarn add --dev tslint tslint-config-blvd tslint-plugin-prettier tslint-config-prettier