Stateless function components are more concise, and there are plans for react to increase performance of them. Good:
export function KuiButton(props) {
return <button className="kuiButton" { ...props } />
};
Bad:
export class KuiButton extends React.Component {
render() {
return <button className="kuiButton" { ...this.props } />
}
}
Good:
export class ClickCounter extends React.Component {
state = { clickCount: 0 };
onClick = () => {
this.setState(prevState => ({
clickCount: prevState.clickCount + 1
}));
}
render() {
return <button className="kuiButton" onClick={ this.onClick } />
}
}
Bad:
export const ClickCounter = React.createClass({
getInitialState() {
return {
clickCount: 0
};
},
onClick() {
this.setState(prevState => ({
clickCount: prevState.clickCount + 1
}));
},
render() {
return <button className="kuiButton" onClick={ this.onClick } />
}
});
When a state change involves the previous state or props, pass setState a function instead of an object.
https://facebook.github.io/react/docs/react-component.html#setstate
Good:
this.setState((prevState, props) => ({
clickCount: prevState.clickCount + props.incrementValue
}));
Bad:
this.setState({ clickCount: this.state.clickCount + this.props.incrementValue });
Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
This will be even more important when the fibers-based implementation is released:
- https://github.com/acdlite/react-fiber-architecture
- https://www.youtube.com/watch?v=ZCuYPiUIONs
reactDirective and react-component are two different ways of embedding react in angular. Using react-component
means adding a bunch of components into angular, while reactDirective
keeps them isolated, and is also a more succinct syntax.
Good:
<hello-component fname="person.fname" lname="person.lname" watch-depth="reference"></hello-component>
Bad:
<react-component name="HelloComponent" props="person" watch-depth="reference" />
Good:
button.js:
export function KuiButton(props) {
return <button className="kuiButton" { ...props } />
};
Bad:
button.js:
export function Button(props) {
return <button className="kuiButton" { ...props } />
};
The filenames leave it off because snake casing already increases file name length.
Name action functions in the form of a strong verb and passed properties in the form of on. E.g:
<sort-button onClick={ action.sort }/>
<pagerButton onPageNext={ action.turnToNextPage } />
Best (relies on stage 2 proposal):
export class ClickCounter extends React.Component {
state = { clickCount: 0 };
// This syntax ensures `this` is bound within handleClick
onClick = () => {
this.setState(prevState => { clickCount: prevState.clickCount + 1 });
}
render() {
return <button className="kuiButton" onClick={ this.onClick } />
}
}
Good:
export class ClickCounter extends React.Component {
constructor() {
this.state = { clickCount: 0 };
this.onClick = this.onClick.bind(this);
}
onClick() {
this.setState(prevState => { clickCount: prevState.clickCount + 1 });
}
render() {
return <button className="kuiButton" onClick={ this.onClick } />
}
}
Bad:
export class ClickCounter extends React.Component {
state = { clickCount: 0 };
onClick() {
this.setState(prevState => { clickCount: prevState.clickCount + 1 });
}
render() {
return <button className="kuiButton" onClick={ () => this.onClick() } />
}
}
Background: https://facebook.github.io/react/docs/handling-events.html There is also an eslint rule we should be able to turn on for this.
Good:
this.setState(prevState => { clickCount: prevState.clickCount + 1 });
Bad:
this.state.clickCount += 1;
Good:
this.setState({
currentPage: 0,
selectedIds: []
});
Discouraged:
this.setState({
pager: new Pager(),
selectedIds: new SelectedIds()
});
render() {
return <button className="kuiButton" { ...this.props } />
}
export function Button({ className, ...rest }) {
const classNames = classNames('KuiButton', className);
return <button className={ classNames } { ...rest } />
};
Pure functions are easier to understand. We don't want to have to think about side effects or mutated state. When invoking a pure function, all we have to think about is what goes in and what comes out.