I've another article about React's 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
Without wasting time, let's look at some more best practices and patterns to reduce code. We'll start with the most common ones.
Use the self-closing tag if the component doesn't have children's props.
return <Component></Component>;
Good code:
return <Component />;
Don't write functions inside jsx elements.
return (
<div>
<button
onClick={() => {
setCount(1);
// ...
}}
>
Click
</button>
</div>
);
Good code:
const onClick = useCallback(() => {
setCount(1);
// ...
}, [deps]);
return (
<div>
<button onClick={onClick}>Click</button>
</div>
);
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.
const [count, setCount] = useState(0);
const [name, setName] = useState("");
const onClick = () => {
setTimeout(() => {
setName("John");
setCount(count + 1);
}, 1000);
};
Good code:
const [state, setState] = useState({
count: 0,
name: "",
});
const onClick = () => {
setTimeout(() => {
setState((prevState) => ({
...prevState,
name: "John",
count: prevState.count + 1,
}));
}, 1000);
};
Note: React 18 adds automatic batching, so multiple updates will be taken care of 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.
return <div style={{ backgroundColor: "red" }}></div>;
Good code:
const Container = styled.div`
background-color: ${({ theme }) => theme.colors.background};
padding: 1rem;
`;
Better code:
const getPrimaryColor = ({ theme }) => theme.colors.primary;
const getDefaultColor = ({ theme }) => theme.colors.secondary;
const Button = styled.button`
background-color: ${getPrimaryColor};
color: ${getDefaultColor};
`;
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.
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>;
}
}
Good code:
const Counter = () => {
const [count, setCount] = useState(0);
const onClick = () => setCount(count + 1);
return <button>Click me</button>;
};
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.
return (
<ui>
{items.map((item) => (
<Component>{item}</Component>
))}
</ui>
);
Good code:
const MemoComponent = React.memo(Component);
return (
<ui>
{items.map((item) => (
<MemoComponent>{item}</MemoComponent>
))}
</ui>
);
NOTE: Use React.memo()
wisely, don't use memo where the component often re-renders with props.
Use JSX ShortHand, Try to use JSX shorthand for passing boolean variables.
return <button disabled={true}>Submit</button>;
Good code:
return <button disabled>Submit</button>;
Use the ternary operator instead of the if-else statement.
if (isLoading) {
return <div>Loading...</div>;
} else {
return <div>Data</div>;
}
Good code:
return isLoading ? <div>Loading...</div> : <div>Data</div>;
Use object(Map) instead of the switch statement. I've already mentioned the same in my previous article for reducers.
switch (props.type) {
case "ADMIN":
return <Admin />;
case "USER":
return <User />;
default:
return <NotFound />;
}
Good code:
const componentMap = {
ADMIN: Admin,
USER: User,
NOT_FOUND: NotFound,
};
const Component = componentMap[props.type];
return <Component />;
Better code:
const componentMap = {
ADMIN: React.lazy(() => import("../components/Admin")),
USER: React.lazy(() => import("../components/User")),
NOT_FOUND: React.lazy(() => import("../components/NotFound")),
};
const Component = componentMap[props.type];
return <Component />;
Use object destructuring instead of passing multiple props by name to a component.
const { name, age, role } = props;
return (
<>
<Component name={name} age={age} role={role} />
</>
);
Good code:
return (
<>
<Component {...props} />
</>
);
Don't need curly braces when you won't pass the string to a component.
return <Component name={"John"} />;
Good code:
return <Component name="John" />;
Don't use react element props like className
, style
etc for component custom props.
return (
<Component style="bordered">
);
Good code:
return (
<Component variant="bordered">
);
Use fragments instead of HTML elements like div, span, etc.
return (
<div>
<span>{props.name}</span>
<span>{props.age}</span>
</div>
);
Good code:
return (
<>
<span>{props.name}</span>
<span>{props.age}</span>
</>
);
Don't use the else block if if
block returns something.
if (props.name) {
return <div>{props.name}</div>;
} else {
return <div>No name</div>;
}
Good code:
if (props.name) {
return <div>{props.name}</div>;
}
return <div>No name</div>;
Use React.ragment instead of Html elements like div, span, etc
return (
<container>
{list.map((item) => (
<div key={item.id}>
<SomeComponent />
<SomeAnotherComponent />
</div>
))}
</container>
);
Good code:
return (
<>
{list.map((item) => (
<React.Fragment key={item.id}>
<SomeComponent />
<SomeAnotherComponent />
</React.Fragment>
))}
</>
);
Thank you for reading ๐
Got any questions or additional? please leave a comment.