DEV Community

Cover image for React best practices and patterns to reduce code - Part 2
Rahul Sharma
Rahul Sharma

Posted on • Edited on

React best practices and patterns to reduce code - Part 2

I've another article about React best practices and patterns to reduce code. It's a good article to read before you start to write your own React code.

React best practices and patterns to reduce code - Part 1

React best practices and patterns to reduceΒ code

Without wasting time, let's look at some more best practices and patterns to reduce code. We'll start with the most common ones.

If the component doesn't have children's props, use the self-closing tag.

Bad code:
return <Component></Component>;
Enter fullscreen mode Exit fullscreen mode
Good code:
return <Component />;
Enter fullscreen mode Exit fullscreen mode

Don't write functions inside jsx elements.

Bad code:
return (
  <div>
    <button
      onClick={() => {
        setCount(1);
        // ...
      }}
    >
      Click
    </button>
  </div>
);
Enter fullscreen mode Exit fullscreen mode
Good code:
const onClick = useCallback(() => {
  setCount(1);
  // ...
}, [deps]);

return (
  <div>
    <button onClick={onClick}>Click</button>
  </div>
);
Enter fullscreen mode Exit fullscreen mode

Use object state if you have to update multiple states together.

Avoid using multiple setState calls in a row. This is a common mistake that can lead to a lot of unnecessary re-renders. It's better to use a single setState call.

Bad code:
const [count, setCount] = useState(0);
const [name, setName] = useState("");

const onClick = () => {
  setTimeout(() => {
    setName("John");
    setCount(count + 1);
  }, 1000);
};
Enter fullscreen mode Exit fullscreen mode
Good code:
const [state, setState] = useState({
  count: 0,
  name: "",
});

const onClick = () => {
  setTimeout(() => {
    setState((prevState) => ({
      ...prevState,
      name: "John",
      count: prevState.count + 1,
    }));
  }, 1000);
};
Enter fullscreen mode Exit fullscreen mode

Note: React 18 adds automatic batching, so multiple updates will be taken care by react itself.


Use styled-components to style your components. This is a good way to avoid writing CSS in JSX and also helps to avoid CSS setup for the application.

It's completely opinion based.

Bad code:
return <div style={{ backgroundColor: "red" }}></div>;
Enter fullscreen mode Exit fullscreen mode
Good code:
const Container = styled.div`
  background-color: ${({ theme }) => theme.colors.background};
  padding: 1rem;
`;
Enter fullscreen mode Exit fullscreen mode
Better code:
const getPrimaryColor = ({ theme }) => theme.colors.primary;
const getDefaultColor = ({ theme }) => theme.colors.secondary;

const Button = styled.button`
  background-color: ${getPrimaryColor};
  color: ${getDefaultColor};
`;
Enter fullscreen mode Exit fullscreen mode

Note: Create functions to get color and other styles from the theme and pass them to styled components. This will also help to reduce code.


Try to avoid class-based components and use functional components instead.

Bad code:
class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
    this.onClick = this.onClick.bind(this);
  }

  onClick = () => {
    this.setState({
      count: this.state.count + 1,
    });
  };

  render() {
    return <button onClick>Click me</button>;
  }
}
Enter fullscreen mode Exit fullscreen mode
Good code:
const Counter = () => {
  const [count, setCount] = useState(0);
  const onClick = () => setCount(count + 1);
  return <button>Click me</button>;
};
Enter fullscreen mode Exit fullscreen mode

NOTE: Functional components not only reduces development time and code but also decrease production bundle size. It reduces the bundle size by almost ~60%.


React.memo to avoid unnecessary re-renders.

Bad code:
return (
  <ui>
    {items.map((item) => (
      <Component>{item}</Component>
    ))}
  </ui>
);
Enter fullscreen mode Exit fullscreen mode
Good code:
const MemoComponent = React.memo(Component);
return (
  <ui>
    {items.map((item) => (
      <MemoComponent>{item}</MemoComponent>
    ))}
  </ui>
);
Enter fullscreen mode Exit fullscreen mode

NOTE: Use React.memo() wisely, don't use memo where component often re-renders with props.


Use JSX ShortHand, Try to use JSX shorthand for passing boolean variables.

Bad code:
return <button disabled={true}>Submit</button>;
Enter fullscreen mode Exit fullscreen mode
Good code:
return <button disabled>Submit</button>;
Enter fullscreen mode Exit fullscreen mode

Use ternary operator instead of if-else statement.

Bad code:
if (isLoading) {
  return <div>Loading...</div>;
} else {
  return <div>Data</div>;
}
Enter fullscreen mode Exit fullscreen mode
Good code:
return isLoading ? <div>Loading...</div> : <div>Data</div>;
Enter fullscreen mode Exit fullscreen mode

Use object(Map) instead of switch statement. I've already mentioned the same in my previous article for reducers.

Bad code:
switch (props.type) {
  case "ADMIN":
    return <Admin />;
  case "USER":
    return <User />;
  default:
    return <NotFound />;
}
Enter fullscreen mode Exit fullscreen mode
Good code:
const componentMap = {
  ADMIN: Admin,
  USER: User
};

const Component = componentMap[props.type] ?? NotFound;
return <Component />;
Enter fullscreen mode Exit fullscreen mode
Better code:
const NotFound = React.lazy(() => import("../components/NotFound"));
const componentMap = {
  ADMIN: React.lazy(() => import("../components/Admin")),
  USER: React.lazy(() => import("../components/User")),
};

const Component = componentMap[props.type] ?? NotFound;
return <Component />;
Enter fullscreen mode Exit fullscreen mode

Use object destructuring instead of passing multiple props by name to a component.

Bad code:
const { name, age, role } = props;
return (
  <>
    <Component name={name} age={age} role={role} />
  </>
);
Enter fullscreen mode Exit fullscreen mode
Good code:
return (
  <>
    <Component {...props} />
  </>
);
Enter fullscreen mode Exit fullscreen mode

Don't need curly braces when you won't pass the string to a component.

Bad code:
return <Component name={"John"} />;
Enter fullscreen mode Exit fullscreen mode
Good code:
return <Component name="John" />;
Enter fullscreen mode Exit fullscreen mode

Don't use react element props like className, style etc for component custom props.

Bad code:
return (
  <Component style="bordered">
);
Enter fullscreen mode Exit fullscreen mode
Good code:
return (
  <Component variant="bordered">
);
Enter fullscreen mode Exit fullscreen mode

Use fragment instead of html element like div, span, etc.

Bad code:
return (
  <div>
    <span>{props.name}</span>
    <span>{props.age}</span>
  </div>
);
Enter fullscreen mode Exit fullscreen mode
Good code:
return (
  <>
    <span>{props.name}</span>
    <span>{props.age}</span>
  </>
);
Enter fullscreen mode Exit fullscreen mode

Don't use else block if if block returns something.

Bad code:
if (props.name) {
  return <div>{props.name}</div>;
} else {
  return <div>No name</div>;
}
Enter fullscreen mode Exit fullscreen mode
Good code:
if (props.name) {
  return <div>{props.name}</div>;
}
return <div>No name</div>;
Enter fullscreen mode Exit fullscreen mode

Use React.fragment instead of Html element like div, span, etc when you won't use the key property.

Bad code:
return (
  <container>
    {list.map((item) => (
      <div key={item.id}>
        <SomeComponent />
        <SomeAnotherComponent />
      </div>
    ))}
  </container>
);
Enter fullscreen mode Exit fullscreen mode
Good code:
return (
  <>
    {list.map((item) => (
      <React.Fragment key={item.id}>
        <SomeComponent />
        <SomeAnotherComponent />
      </React.Fragment>
    ))}
  </>
);
Enter fullscreen mode Exit fullscreen mode

Thank you for reading 😊

Got any questions or additional? please leave a comment.


Must Read If you haven't

Catch me on

Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon

Latest comments (36)

Collapse
 
dmytro_dmytro_dmytro profile image
Dmytro Dmytro

Useful! Thanks! I would recommend to read this one: webman.pro/blog/react-best-practices/

Collapse
 
cteyton profile image
CΓ©dric Teyton

Hello Rahul, FYI we've added your blog post on a GitHub project gathering content about best coding practices :)
github.com/promyze/best-coding-pra...

Collapse
 
slopez93 profile image
Santi LΓ³pez Bayo

You can comment also here:

eccco.space/s/cadf73c1-1900-4fe8-a...

Collapse
 
gabrielmlinassi profile image
Gabriel Linassi • Edited

I'd add some more:

  1. Composition
  2. Extract useEffect logic into a custom hook
  3. Try to use useRef instead of useState for inputs
  4. Don't put into state info you can get from reading other states

Examples:

<Layout>
   <Layout.SidePanel>{ ... }</Layout.SidePanel>
   <Layout.Main>{ ... }</Layout.Main>
</Layout>
Enter fullscreen mode Exit fullscreen mode
const { cart, loading, error } = useCart()
...
return cart.items.map(item => (...))
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ianhfar profile image
ianhfar

"Use styled-components to style your components."
This should be highlighted as your opinion.
Not sure you can argue this is a must.

By separating your styling into a css file, you are not polluting your source with styling.

Collapse
 
devsmitra profile image
Rahul Sharma

Thanks for suggestions, I've added.

Collapse
 
manssorr profile image
Mansour Koura

HEY MAN! YOU ARE AWESOME!

  • Use object(Map) instead of switch statement. I've already mentioned the same in my previous article for reducers.
  • Use styled-components to style your components. This is a good way to avoid writing CSS in JSX and also helps to avoid CSS setup for the application.
  • Use object state if you have to update multiple states together.
  • Don't write functions inside JSX elements.

All of those ones Realy amazing! and I will start using them immediately, please write more!

Collapse
 
sharan98727 profile image
sharan

const onClick = useCallback(() => {
setCount(1);
// ...
}, [deps]);

return (


Click

);

Why are we using usecallback here. is there any specific reason here.

Collapse
 
nokternol profile image
Mark Butterworth

If setCount was the only thing called then it would be pointless but all these hooks are just different forms of memoization used for different purposes.

useCallback creates a cached method preventing a re-render if the deps did not change. useState dispatcher already does this so memoizing it alone adds no value.

Collapse
 
ekdikeo profile image
Eric B

Use object state if you have to update multiple states together

Not really, no. Use useReducer.

Use styled-components

No.

Use object(Map) instead of switch statement

... while there are places where this does make sense, especially if you're in a component that is otherwise 100% declarative, for the most part, avoid.

Use object destructuring instead of passing multiple props by name to a component

Absolutely not. Always pass exactly the parameters you need. Do not ever pass a wholesale ...rest props to a component.

Use fragment

Wow! OK, I was not aware of Fragment. Great tip . . . when it's useful. It has a specific purpose, and your example is not it.

Collapse
 
torver213 profile image
Peter Kelvin Torver

"Use React.memo() wisely, don't use memo where component often re-renders with props."
Can u explain why? Supposing I have a child component that takes props, what you suggest I should? Don't call React.memo() on the child component?

Collapse
 
devsmitra profile image
Rahul Sharma

don't use memo where component often re-renders because of props. React.memo does not help because it's anyway going re-render.

Collapse
 
msaperst profile image
Max Saperstone

This is a great article. One thing I've done in the past is setup ESLint to catch some things like this. I'll look to see if I can add some more, but it'll auto catch and even fix a lot of these things

Some comments have been hidden by the post's author - find out more