DEV Community

Cover image for React Best Practices with Examples
Philip Walsh
Philip Walsh

Posted on

React Best Practices with Examples

React is a powerful library for building user interfaces. Following best practices ensures maintainable, performant, and scalable code. Here's a comprehensive guide based on React's documentation and community insights.


Core Best Practices from React Docs

1. Treat Props as Readonly

Props must not be modified. Treat them as immutable inputs.

function Welcome({ name }) {
  return <h1>Hello, {name}!</h1>; // Avoid modifying props directly
}
Enter fullscreen mode Exit fullscreen mode

2. State Management

  • Always use setState or equivalent to modify state.

setState(prev => ({ count: prev.count + 1 }));
Enter fullscreen mode Exit fullscreen mode
  • Clean up resources like timers in lifecycle methods or useEffect:
useEffect(() => {
  const timer = setInterval(() => console.log('Tick'), 1000);
  return () => clearInterval(timer); // Cleanup
}, []);
Enter fullscreen mode Exit fullscreen mode

3. Bind Functions Efficiently

Use arrow functions or bind functions in the constructor.

class MyComponent extends React.Component {
  constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Use Stable Keys for Lists

Provide unique, stable keys when rendering lists.

const items = ['Apple', 'Banana'];
items.map(item => <li key={item}>{item}</li>);
Enter fullscreen mode Exit fullscreen mode

5. Lift State Up

Share state by lifting it to the nearest common ancestor.

function Parent() {
  const [value, setValue] = useState('');
  return (
    <>
      <ChildInput value={value} onChange={setValue} />
      <ChildDisplay value={value} />
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

6. Avoid Context Misuse

Reserve context for specific cases like theming or authentication.

const ThemeContext = React.createContext('light');
Enter fullscreen mode Exit fullscreen mode

7. Leverage Pure Components

Optimize performance using React.PureComponent or React.memo.

const MemoizedComponent = React.memo(({ value }) => <div>{value}</div>);
Enter fullscreen mode Exit fullscreen mode

Presentation vs. Container Components

  • Presentational Components handle UI rendering.
  • Container Components manage state and logic.

Example:

function Button({ label, onClick }) {
  return <button onClick={onClick}>{label}</button>; // Presentational
}

function Counter() {
  const [count, setCount] = useState(0);
  return <Button label={`Count: ${count}`} onClick={() => setCount(count + 1)} />; // Container
}
Enter fullscreen mode Exit fullscreen mode

Performance Optimizations

1. Avoid Mutating State

Use the spread operator or immutable libraries.

const newState = { ...oldState, key: 'newValue' };
Enter fullscreen mode Exit fullscreen mode

2. Avoid Index as Keys

Using indices can lead to issues during reordering.

const list = ['A', 'B'];
list.map(item => <div key={item}>{item}</div>);
Enter fullscreen mode Exit fullscreen mode

3. Memoize Expensive Operations

Use useMemo and useCallback to optimize calculations.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Enter fullscreen mode Exit fullscreen mode

Additional Best Practices

Prefer Functional Components

Use functional components with hooks over class-based ones.

function MyComponent() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Define defaultProps

Provide default values for props.

Button.defaultProps = {
  label: 'Click me',
};
Enter fullscreen mode Exit fullscreen mode

Avoid Overusing State

Keep state minimal and centralized.

const initialState = { user: null, theme: 'dark' };
Enter fullscreen mode Exit fullscreen mode

Normalize Data Structures

Use normalized formats for entities.

const state = {
  users: { 1: { id: 1, name: 'John' } },
  posts: { 1: { id: 1, title: 'Hello', authorId: 1 } },
};
Enter fullscreen mode Exit fullscreen mode

Anti-Patterns to Avoid

1. Nested State

Deeply nested states make updates cumbersome.

// Avoid this
const state = { user: { preferences: { theme: 'dark' } } };
Enter fullscreen mode Exit fullscreen mode

2. Logic in Render Methods

Cache derived data instead of recalculating during renders.

const derived = useMemo(() => items.filter(item => item.active), [items]);
Enter fullscreen mode Exit fullscreen mode

3. Inline Functions in JSX

Declare functions outside render for performance.

const handleClick = () => setState(state + 1);
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

By adhering to these best practices, you’ll write cleaner, more efficient React code.
Consistency leads to fewer bugs, better performance, and improved collaboration.
Apply these tips, and you’ll level up your React projects!

Top comments (1)

Collapse
 
brense profile image
Rense Bakker

Class components are deprecated for a while now. So, binding functions is not something you have to do anymore.

Since React 19, defaultProps are also deprecated, use es6 syntax for assigning default values for your component props:

const Button = ({ size = "16px", color = "blue" }) => {
  return <button style={{ color, fontSize: size }}>Click me</button>;
};
Enter fullscreen mode Exit fullscreen mode