10 ReactJS Anti-Patterns to Avoid

Posted on
Picture of the post 10 ReactJS Anti-Patterns to Avoid
Photo by Luca Bravo on Unsplash

ReactJS is a powerful library for building dynamic user interfaces, but certain practices can lead to inefficiencies and hard-to-maintain code. Here are ten common anti-patterns in React development and how to avoid them. 1. Big Components Large components can be hard to manage and understand. Refactor them into smaller, reusable components. Use the Glean extension for VSCode to help refactor your code efficiently. 2. Nesting Components Defining child components inside parent components can cause unnecessary re-renders, leading to performance issues. Anti-Pattern:

function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => setCount(count + 1);
  const Child = () => {
    return <button onClick={handleClick}>+</button>;
  };
  return (
    <div>
      <Child />
    </div>
  );
}
Solution:
const Child = ({ onClick }) => {
  return <button onClick={onClick}>+</button>;
};
function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () => setCount(count + 1);
  return (
    <div>
      <Child onClick={handleClick} />
    </div>
  );
}
3. Failure to Memorize Expensive calculations should be memoized to prevent unnecessary recalculations using the useMemo hook. Solution:
export default function MyComponent({values}: props) 
{
const total = useMemo(() => expensiveCalculation(values), [values]);
return <span>{total}</span>;
}
4. Useless Divs Using unnecessary divs can clutter your HTML and cause CSS issues. Use fragments instead. Solution:
return (
  <>
    <nav></nav>
    <article></article>
  </>
);
For collections of items, use React.Fragment with a key.
function NavBar() {  
	return menu.map(item =>  
		<React.Fragment key={item.id}>
		  <NavTitle title={item.title} />  
		  <Icon icon={item.icon} />  
		</React.Fragment>  
	);  
}
5. Messy Files Organize your components by following the "one component per file" rule or using directories to group related files. Structure:
MyComponent/
  index.tsx
  MyComponent.module.css
  MyComponent.spec.ts
  MyComponent.stories.js
  MyComponent.tsx
Export and Import:
// index.tsx
export { default } from './MyComponent';
// import from other files
import MyComponent from './MyComponent';
6. Big Bundles Large bundles can slow down your application. Use dynamic imports with React.lazy and Suspense for code splitting. Solution:
import React, { Suspense } from 'react';
const ExpensiveComponent = React.lazy(() => import('./ExpensiveComponent'));
function Page() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <ExpensiveComponent />
    </Suspense>
  );
}
7. Prop Drilling Passing props down through multiple layers of components can make your code harder to manage. Anti-Pattern:
function PropDrilling() {
  const [count] = useState(0);
  return <Child count={count} />;
}
function Child({ count }) {
  return <GrandChild count={count} />;
}
function GrandChild({ count }) {
  return <div>{count}</div>;
}
Solutions: • Use state management libraries. • Use the useContext hook for global values. 8. Prop Plowing Passing many props to a component can lead to messy and hard-to-read code. Anti-Pattern:
<UserComponent id={id} name={name} bio={bio} ... />
Solutions: • Use spread props:
const data = { id: 1, name: 'test', bio: 'lorem' };
<UserComponent {...data} />;
• Use a single props object:
<UserComponent user={user} />;
9. Messy Events Inline event handlers can become unwieldy. Anti-Pattern:
const handleIt = (e, v) => console.log(e, v);
return (
  <div>
    <input onChange={(e) => handleIt(e, 1)} />
    <input onChange={(e) => handleIt(e, 2)} />
    <input onChange={(e) => handleIt(e, 3)} />
  </div>
);
Solution: Use curried functions:
const handleIt = (v) => (e) => console.log(e, v);
return (
  <div>
    <input onChange={handleIt(1)} />
    <input onChange={handleIt(2)} />
    <input onChange={handleIt(3)} />
  </div>
);
10. Coupled State Having a single state object with many properties can make state updates complex. Anti-Pattern:
const [state, setState] = useState({
  title: 'my-post',
  theme: 'dark',
  date: Date.now(),
});
Solution: Break it into multiple states or use custom hooks:
function useMetaData() {
  const [title, setTitle] = useState('my-post');
  const [theme, setTheme] = useState('dark');
  const [date, setDate] = useState(Date.now);
  return { title, theme, date };
}
const { title, theme, date } = useMetaData();
Avoiding these anti-patterns will help you write cleaner, more efficient, and maintainable ReactJS code.