React Tips and Tricks for Efficient Development
None of what follows is a trick in the sense of being clever. They are the habits that separate a component someone else can pick up from one that has to be rewritten, and most of them cost nothing at the time and save a great deal later.
Insights: Why Efficient React Coding Matters
React is a powerful tool, but writing efficient code can make a big difference in your app’s performance and usability. Here’s why these best practices matter:
- Better Performance: Optimised components render faster, improving user experience.
- Easier Maintenance: Clean and consistent code is easier to update and debug.
- Cost-Effective: Efficient code means shorter development times and fewer bugs.
- Improved Accessibility: A streamlined DOM structure benefits all users.
React Best Practices and Tips
Avoid Multiple Wrapper Elements
Reduce unnecessary DOM nodes using React fragments (<> </>). This enhances performance and keeps your component tree clean.
// Bad Practice
function Layout() {
return (
<div>
<header>Header</header>
<main>Main Content</main>
</div>
);
}
// Good Practice
function Layout() {
return (
<>
<header>Header</header>
<main>Main Content</main>
</>
);
}- Reduces unnecessary DOM nodes
- Improves rendering performance
- Cleaner and more readable code
Simplify Conditional Rendering
Write concise and readable conditions using short-circuit operators (&&) and ternary operators.
Use Short-Circuiting (&&) for Simple Conditions:
// Bad Practice
{isLoggedIn ? <p>Welcome back!</p> : null}
// Good Practice
{isLoggedIn && <p>Welcome back!</p>}Use Ternary Operators for Dual Outcomes:
// Bad Practice
{isLoading ? (
<p>Loading...</p>
) : (
<p>Data loaded!</p>
)}
// Good Practice
<p>{isLoading ? "Loading..." : "Data loaded!"}</p>- Makes JSX more concise and readable
- Reduces code duplication
Use Default Props
Ensure components have fallback values to prevent rendering issues.
function Greeting({ name = "Guest" }) {
return <h1>Hello, {name}!</h1>;
}- Prevents unexpected undefined values
- Simplifies component usage
- Provides sensible defaults
Use Self-Closing Tags
Simplify your JSX syntax with self-closing tags for components without children.
// Bad Practice
<img src="logo.png"></img>
// Good Practice
<img src="logo.png" />- Reduces visual clutter in JSX
- Prevents bugs from missing closing tags
- Aligns with modern HTML practices
Use Key Props in Lists
Assign unique keys to list items to help React optimise re-rendering.
Avoid Using Index as Key (When Possible):
// Bad Practice
{items.map((item, index) => (
<li key={index}>{item.name}</li>
))}
// Good Practice
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}- Improves rendering performance
- Reduces bugs during reordering
- Helps React identify which items changed
Use useCallback for Stable Functions
Optimise performance by preventing unnecessary re-renders with useCallback.
function ParentComponent() {
const handleClick = () => {
console.log("Clicked");
};
return <ChildComponent onClick={handleClick} />;
}import { useCallback } from "react";
function ParentComponent() {
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
return <ChildComponent onClick={handleClick} />;
}- Improves performance in large applications
- Prevents unnecessary re-renders of child components
- Optimises memoised components ( React.memo )
Use export default for Main Components
Use export default for better code organisation and easier imports.
// Exporting
export default function Header() {
return <h1>Header</h1>;
}
// Importing
import Header from './Header';- Easier to import components
- Reduces confusion with multiple named exports
- Simplifies file organisation
Avoid Inline Styles
Separate your styles from components using external CSS or styled-components.
// Bad Practice
<div style={{ color: 'red', fontSize: '20px' }}>Hello</div>Use CSS Modules or Styled Components:
// Good Practice (CSS Module)
import styles from './Button.module.css';
function Button() {
return <button className={styles.primary}>Click Me</button>;
}import styled from 'styled-components';
const Button = styled.button`
color: white;
background-color: blue;
font-size: 16px;
`;
function App() {
return <Button>Styled Button</Button>;
}- Keeps JSX clean and focused on structure
- Improves styling consistency
- Allows style reuse and theming
Performance: Load Less, Render Less
The tips above keep code clean. These four keep a growing app fast.
Split Code with React.lazy and Suspense
Load a heavy component only when it is needed, instead of in the first bundle:
import React, { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
const App = () => {
return (
<Suspense fallback={<p>Loading component...</p>}>
<HeavyComponent />
</Suspense>
);
};
export default App;The same idea works per route: lazy-load each page so a visitor downloads only the page they open. Most routers and frameworks, Next.js included, split code by route for you.
Skip Re-renders with React.memo
React.memo re-renders a component only when its props change. It pairs with useCallback above: a memoised child is only skipped if the functions passed to it keep the same reference.
import React from 'react';
const Button = React.memo(({ onClick, label }) => {
console.log("Rendering Button");
return <button onClick={onClick}>{label}</button>;
});
export default Button;Cache Expensive Values with useMemo
useMemo recalculates a value only when its dependencies change. Use it for genuinely expensive work such as filtering or sorting a large list, not for simple arithmetic, where the memoisation costs more than it saves. In short: useMemo caches a value, useCallback caches a function, and React.memo caches a component's output.
Serve Smaller Images
- Use modern formats such as AVIF and WebP, and SVG for icons and logos
- Add loading="lazy" to images below the fold so they load as the user scrolls
- Serve different sizes for different screens with srcset and sizes
- Compress images before upload, or use an image CDN that does it for you
Frequently Asked Questions (FAQs)
Why should I use React Fragments instead of wrapper <div> elements?
React Fragments help reduce unnecessary DOM nodes, making your page load faster and your component structure cleaner.
How do default props improve my React app?
Default props ensure your components function even if no values are passed, preventing undefined errors and improving user experience.
What is the impact of using useCallback on performance?
useCallback prevents unnecessary re-renders by memoising functions, which is particularly useful in apps with many child components.
Are inline styles bad for performance?
Yes, because inline styles reduce page loading efficiency and caching capabilities. Using external styles or CSS-in-JS libraries like styled-components is better.
Should I always use export default for React components?
While not mandatory, using export default for primary components simplifies imports and maintains consistency across your project.
Why is using unique keys in lists important for performance?
Unique keys help React identify which items have changed, improving rendering efficiency and preventing layout issues.
Watch these React tips on YouTube(opens in a new tab)
A short video walkthrough of the same tips, if you would rather watch than read.