0% found this document useful (0 votes)
10 views

101_react_tips_and_tricks

Uploaded by

tienkhoa280310
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

101_react_tips_and_tricks

Uploaded by

tienkhoa280310
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 142

101 React Tips & Tricks

Written by Ndeye Fatou Diop

© 2024 Ndeye Fatou Diop.

All rights reserved. The author has taken care in preparation of this
book, but makes no expressed or implied warranty of any kind, and
assumes no responsibility for errors or omissions. No liability is
assumed for incidental or consequential damages in with or arising
out of the use of the information contained herein.

This book is self-published.


101 React Tips & Tricks 1 / 140

THIS BOOK BELONGS TO

This digital workbook is made available to you for


personal use only. You may use, reuse, print and reprint
the pages of this book as many times as you like for
your own personal reference, but please do not share any
part of this book (either digitally or in print) with others.

Instead, you can direct them to


https://ndeyefatoudiop.gumroad.com/l/101-react-tips-
and-tricks, where I offer this book for free.

Thank you!

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 2 / 140

INTRODUCTION

I have been working professionally with React since


2019.

In this article, I share the 101 best tips & tricks I learned
over the years.

This guide assumes a basic familiarity with React


and an understanding of the terms props ,
state , context , etc.
I tried to use Vanilla JS for most of the examples to
keep things simple. If you're using TypeScript, you
can easily adapt the code.
The code is not production-ready. Use at your own
discretion.
If you have any questions or suggestions, feel free
to reach out to me on Twitter @_ndeyefatoudiop.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 3 / 140

TABLE OF CONTENTS

Category #1: Components organization 🧹


1. Use self-closing tags to keep your code
compact
2. Prefer fragments over DOM nodes (e.g.,
div, span, etc.) to group elements
3. Use React fragment shorthand <></>
(except if you need to set a key)
4. Prefer spreading props over accessing each
one individually
5. When setting default values for props, do it
while destructuring them
6. Drop curly braces when passing string
type props.
7. Ensure that value is a boolean before
using value && <Component
{...props}/> to prevent displaying
unexpected values on the screen.
8. Use functions (inline or not) to avoid
polluting your scope with intermediate
variables
9. Use curried functions to reuse logic (and
properly memoize callback functions)
10. Move data that doesn't rely on the
component props/state outside of it for
cleaner (and more efficient) code
11. When storing the selected item from a list,
store the item ID rather than the entire item
12. If you're frequently checking a prop's value
before doing something, introduce a new
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 4 / 140

component
13. Use the CSS :empty pseudo-class to
hide elements with no children
14. Group all the state and context at the top
of the component
Category #2: Effective Design Patterns &
Techniques 🛠
15. Leverage the children props for cleaner
code (and performance benefits)
16. Build composable code with compound
components
17. Make your code more extensible with
render functions or component
functions props
18. When dealing with different cases, use
value === case && <Component /> to
avoid holding onto old state
19. Always use error boundaries
Category #3: Keys & Refs 🗝
20. Use crypto.randomUUID or
Math.random to generate keys
21. Make sure your list items IDs are stable
(i.e., they don't change between renders)
22. Strategically use the key attribute to
trigger component re-renders
23. Use a ref callback function for
tasks such as monitoring size changes and
managing multiple node elements.
Category #4: Organizing React code 🧩
24. Colocate React components with their
assets (e.g., styles, images, etc.)
25. Limit your component file size

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 5 / 140

26. Limit the number of return statements in


your functional component file
27. Prefer named exports over default exports
Category #5: Efficient State Management 🚦
28. Never create a state for a value that can
be derived from other state or props
29. Keep the state at the lowest level
necessary to minimize re-renders
30. Clarify the distinction between the initial
state and the current state
31. Update state based on the previous state,
especially when memoizing with
useCallback
32. Use functions in useState for lazy
initialization and performance gains, as they
are invoked only once.
33. Use react context for broadly needed,
static state to prevent prop drilling
34. React Context: Split your context into
parts that change frequently and those that
change infrequently to enhance app
performance
35. React Context: Introduce a Provider
component when the value computation is
not straightforward
36. Consider using the useReducer hook
as a lightweight state management solution
37. Simplify state updates with useImmer
or useImmerReducer
38. Use Redux (or another state management
solution) for complex client-side state
accessed across multiple components

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 6 / 140

39. Redux: Use Redux DevTools to debug your


state
Category #6: React Code Optimization 🚀
40. Prevent unnecessary re-renders with
memo
41. Specify an equality function with memo to
instruct React on how to compare the props.
42. Prefer named functions over arrow
functions when declaring a memoized
component
43. Cache expensive computations or
preserve references with useMemo
44. Use useCallback to memoize
functions
45. Memoize callbacks or values returned
from utility hooks to avoid performance
issues
46. Leverage lazy loading and Suspense to
make your apps load faster
47. Throttle your network to simulate a slow
network
48. Use react-window or react-
virtuoso to efficiently render lists
Category #7: Debugging React code 🐞
49. Use StrictMode to catch bugs in your
components before deploying them to
production
50. Install the React Developer Tools browser
extension to view/edit your components and
detect performance issues
51. React DevTools Components: Highlight
components that render to identify potential

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 7 / 140

issues
52. Leverage useDebugValue in your
custom hooks for better visibility in React
DevTools
53. Use the why-did-you-render library
to track component rendering and identify
potential performance bottlenecks
54. Hide logs during the second render in
Strict Mode
Category #8: Testing React code 🧪
55. Use React Testing Library to test
your React components effectively
56. React Testing Library: Use testing
playground to effortlessly create queries
57. Conduct end-to-end tests with Cypress
or Playwright
58. Use MSW to mock network requests in
your tests
Category #9: React hooks 🎣
59. Make sure you perform any required
cleanup in your useEffect hooks
60. Use refs for accessing DOM elements
61. Use refs to preserve values across re-
renders
62. Prefer named functions over arrow
functions within hooks such as useEffect
to easily find them in React Dev Tools
63. Encapsulate logic with custom hooks
64. Prefer functions over custom hooks
65. Prevent visual UI glitches by using the
useLayoutEffect hook

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 8 / 140

66. Generate unique IDs for accessibility


attributes with the useId hook
67. Use the useSyncExternalStore to
subscribe to an external store
68. Use the useDeferredValue hook to
display the previous query results until the
new results become available
Category #10: Must-known React Libraries/Tools 🧰
69. Incorporate routing into your app with
react-router
70. Implement first-class data fetching in
your app with swr or React Query
71. Simplify form state management with
libraries like formik , React Hook Form ,
or TanStack Form
72. Internationalize your app using
Format.js, Lingui, or react-
i18next.
73. Effortlessly create impressive animations
with framer-motion
74. Tired of re-inventing the wheel with
custom hooks? Check out
https://usehooks.com/
75. Streamline app development by
leveraging UI libraries like Shadcdn or
Headless UI
76. Check your website's accessibility with
the axe-core-npm library
77. Refactor React code effortlessly with
react-codemod
78. Transform your app into a Progressive Web
Application (PWA) using vite-pwa

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 9 / 140

Category #11: React & Visual Studio Code 🛠


79. Enhance your productivity with the Simple
React Snippets snippets extension
80. Set editor.stickyScroll.enabled
to true to quickly locate the current
component
81. Simplify refactoring with extensions like
VSCode Glean or VSCode React Refactor
Category #12: React & TypeScript 🚀
82. Use ReactNode instead of
JSX.Element | null | undefined |
... to keep your code more compact
83. Simplify the typing of components
expecting children props with
PropsWithChildren
84. Access element props efficiently with
ComponentProps ,
ComponentPropsWithoutRef ,…
85. Leverage types like
MouseEventHandler ,
FocusEventHandler and others for
concise typings
86. Specify types explicitly in useState,
useRef, etc., when the type can't be or
shouldn't be inferred from the initial value
87. Leverage the Record type for cleaner
and more extensible code
88. Use the as const trick to accurately
type your hook return values
89. Redux: Ensure proper typing by referring
to https://react-redux.js.org/using-react-

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 10 / 140

redux/usage-with-typescript to correctly type


your Redux state and helpers
90. Simplify your types with
ComponentType
91. Make your code more reusable with
TypeScript generics
92. Ensure precise typing with the NoInfer
utility type
93. Effortlessly type refs with the
ElementRef type helper
Category #13: Miscellaneous Tips 🎉
94. Boost your code's quality and safety with
eslint-plugin-react and Prettier.
95. Log and monitor your app with tools like
Sentry or Grafana Cloud Frontend
Observability.
96. Start coding quickly with online IDEs like
Code Sandbox or Stackblitz
97. Looking for advanced react skills? Check
out these books 👇
98. Prepping React interviews? Check reactjs-
interview-questions
99. Learn React best practices from experts
like Nadia, Dan, Josh, Kent, etc.
100. Stay updated with the React ecosystem
by subscribing to newsletters like This Week
In React or ui.dev
101. Engage with the React community on
platforms like r/reactjs

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 11 / 140

CATEGORY #1: COMPONENTS


ORGANIZATION 🧹
➥ Tip # 1. Use self-closing tags to keep your
code compact

// ❌Bad: too verbose


<MyComponent></MyComponent>

// ✅Good
<MyComponent/>

➥ Tip # 2. Prefer fragments over DOM nodes


(e.g., div, span, etc.) to group elements

In React, each component must return a single element.


Instead of wrapping multiple elements in a <div> or
<span> , use <Fragment> to keep your DOM neat and
tidy.

❌ Bad: Using div clutters your DOM and may require


more CSS code.

function Dashboard() {
return (
<div>
<Header />
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 12 / 140

<Main />
</div>
);
}

✅ Good: <Fragment> wraps elements without


affecting the DOM structure.

function Dashboard() {
return (
<Fragment>
<Header />
<Main />
</Fragment>
);
}

➥ Tip # 3. Use React fragment shorthand <>


</> (except if you need to set a key)

❌ Bad: The code below is unnecessarily verbose.


<Fragment>
<FirstChild />
<SecondChild />
</Fragment>

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 13 / 140

✅ Good: Unless, you need a key , <></> is more


concise.

<>
<FirstChild />
<SecondChild />
</>;

// Using a `Fragment` here is required


because of the key.
function List({ users }) {
return (
<div>
{users.map((user) => (
<Fragment key={user.id}>
<span>{user.name}</span>
<span>{user.occupation}</span>
</Fragment>
))}
</div>
);
}

➥ Tip # 4. Prefer spreading props over


accessing each one individually

❌ Bad: The code below is harder to read (especially at


scale).

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 14 / 140

// We do `props…` all over the code.


function TodoList(props) {
return (
<div>
{props.todos.map((todo) => (
<div key={todo}>
<button
onClick={() =>
props.onSelectTodo(todo)}
style={{
backgroundColor: todo ===
props.selectedTodo ? "gold" : undefined,
}}
>
<span>{todo}</span>
</button>
</div>
))}
</div>
);
}

✅ Good: The code below is more concise.


function TodoList({ todos, selectedTodo,
onSelectTodo }) {
return (
<div>
{todos.map((todo) => (
<div key={todo}>
<button
onClick={() =>
onSelectTodo(todo)}
style={{

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 15 / 140

backgroundColor: todo ===


selectedTodo ? "gold" : undefined,
}}
>
<span>{todo}</span>
</button>
</div>
))}
</div>
);
}

➥ Tip # 5. When setting default values for props,


do it while destructuring them

❌ Bad: You may need to define the defaults in multiple


places and introduce new variables.

function Button({ onClick, text, small,


colorScheme }) {
let scheme = colorScheme || "light";
let isSmall = small || false;
return (
<button
onClick={onClick}
style={{
color: scheme === "dark" ? "white"
: "black",
fontSize: isSmall ? "12px" :
"16px",
}}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 16 / 140

>
{text ?? "Click here"}
</button>
);
}

✅ Good: You can set all your defaults in one place at the
top. This makes it easy for someone to locate them.

function Button({
onClick,
text = "Click here",
small = false,
colorScheme = "light",
}) {
return (
<button
onClick={onClick}
style={{
color: colorScheme === "dark" ?
"white" : "black",
fontSize: small ? "12px" : "16px",
}}
>
{text}
</button>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 17 / 140

➥ Tip # 6. Drop curly braces when passing


string type props.

// ❌Bad: curly braces are not needed


<Button text={"Click me"} colorScheme=
{"dark"} />

// ✅Good
<Button text="Click me" colorScheme="dark"
/>

➥ Tip # 7. Ensure that value is a boolean


before using value && <Component
{...props}/> to prevent displaying
unexpected values on the screen.

❌ Bad: When the list is empty, 0 will be printed on the


screen.

export function ListWrapper({ items,


selectedItem, setSelectedItem }) {
return (
<div className="list">
{items.length && ( // `0` if the list
is empty
<List
items={items}
onSelectItem={setSelectedItem}
selectedItem={selectedItem}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 18 / 140

/>
)}
</div>
);
}

✅ Good: Nothing will be printed on the screen when


there are no items.

export function ListWrapper({ items,


selectedItem, setSelectedItem }) {
return (
<div className="list">
{items.length > 0 && (
<List
items={items}
onSelectItem={setSelectedItem}
selectedItem={selectedItem}
/>
)}
</div>
);
}

➥ Tip # 8. Use functions (inline or not) to avoid


polluting your scope with intermediate variables

❌ Bad: The variables gradeSum and gradeCount


are cluttering the component's scope.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 19 / 140

function Grade({ grades }) {


if (grades.length === 0) {
return <>No grades available.</>;
}

let gradeSum = 0;
let gradeCount = 0;

grades.forEach((grade) => {
gradeCount++;
gradeSum += grade;
});

const averageGrade = gradeSum /


gradeCount;

return <>Average Grade: {averageGrade}


</>;
}

✅ Good: The variables gradeSum and


gradeCount are scoped within
computeAverageGrade function.

function Grade({ grades }) {


if (grades.length === 0) {
return <>No grades available.</>;
}

const computeAverageGrade = () => {


let gradeSum = 0;
let gradeCount = 0;
grades.forEach((grade) => {
gradeCount++;
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 20 / 140

gradeSum += grade;
});
return gradeSum / gradeCount;
};

return <>Average Grade:


{computeAverageGrade()}</>;
}

💡 Note: you can also define a function


computeAverageGrade outside the component
and call it inside it.

➥ Tip # 9. Use curried functions to reuse logic


(and properly memoize callback functions)

❌ Bad: The logic for updating a field is very repetitive.


function Form() {
const [{ name, email }, setFormState] =
useState({
name: "",
email: "",
});

return (
<>
<h1>Class Registration Form</h1>
<form>
<label>
Name:{" "}
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 21 / 140

<input
type="text"
value={name}
onChange={(evt) =>
setFormState((formState) =>
({
...formState,
name: evt.target.value,
}))
}
/>
</label>
<label>
Email:{" "}
<input
type="email"
value={email}
onChange={(evt) =>
setFormState((formState) =>
({
...formState,
email: evt.target.value,
}))
}
/>
</label>
</form>
</>
);
}

✅ Good: Introduce
createFormValueChangeHandler that returns the
correct handler for each field.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 22 / 140

Note: This trick is especially nice if you have the


ESLint rule jsx-no-bind turned on. You can just
wrap the curried function inside useCallback
and "Voilà!".

function Form() {
const [{ name, email }, setFormState] =
useState({
name: "",
email: "",
});

const createFormValueChangeHandler =
(field) => {
return (event) => {
setFormState((formState) => ({
...formState,
[field]: event.target.value,
}));
};
};

return (
<>
<h1>Class Registration Form</h1>
<form>
<label>
Name:{" "}
<input
type="text"
value={name}
onChange=
{createFormValueChangeHandler("name")}
/>
</label>
<label>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 23 / 140

Email:{" "}
<input
type="email"
value={email}
onChange=
{createFormValueChangeHandler("email")}
/>
</label>
</form>
</>
);
}

➥ Tip # 10. Move data that doesn't rely on the


component props/state outside of it for cleaner
(and more e cient) code

❌ Bad: OPTIONS and renderOption don't need to


be inside the component because they don't depend on
any props or state.

Also, keeping them inside means we get new object


references every time the component renders. If we were
to pass renderOption to a child component wrapped
in memo , it would break the memoization.

function CoursesSelector() {
const OPTIONS = ["Maths", "Literature",
"History"];
const renderOption = (option: string) =>

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 24 / 140

{
return <option>{option}</option>;
};

return (
<select>
{OPTIONS.map((opt) => (
<Fragment key={opt}>
{renderOption(opt)}</Fragment>
))}
</select>
);
}

✅ Good: Move them out of the component to keep the


component clean and references stable.

const OPTIONS = ["Maths", "Literature",


"History"];
const renderOption = (option: string) => {
return <option>{option}</option>;
};

function CoursesSelector() {
return (
<select>
{OPTIONS.map((opt) => (
<Fragment key={opt}>
{renderOption(opt)}</Fragment>
))}
</select>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 25 / 140

💡 Note: In this example, you can simplify further


by using the option element inline.

const OPTIONS = ["Maths", "Literature",


"History"];

function CoursesSelector() {
return (
<select>
{OPTIONS.map((opt) => (
<option key={opt}>{opt}</option>
))}
</select>
);
}

➥ Tip # 11. When storing the selected item from


a list, store the item ID rather than the entire
item

❌ Bad: If an item is selected but then it changes (i.e.,


we receive a completely new object reference for the
same ID), or if the item is no longer present in the list,
selectedItem will either retain an outdated value or
become incorrect.

function ListWrapper({ items }) {


// We are referencing the entire item
const [selectedItem, setSelectedItem] =
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 26 / 140

useState<Item | undefined>();

return (
<>
{selectedItem != null && <div>
{selectedItem.name}</div>}
<List
items={items}
selectedItem={selectedItem}
onSelectItem={setSelectedItem}
/>
</>
);
}

✅ Good: We store the selected item by its ID (which


should be stable). This ensures that even if the item is
removed from the list or one of its properties changed,
the UI should be correct.

function ListWrapper({ items }) {


const [selectedItemId, setSelectedItemId]
= useState<number | undefined>();
// We derive the selected item from the
list
const selectedItem = items.find((item) =>
item.id === selectedItemId);

return (
<>
{selectedItem != null && <div>
{selectedItem.name}</div>}
<List
items={items}
selectedItemId={selectedItemId}
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 27 / 140

onSelectItem={setSelectedItemId}
/>
</>
);
}

➥ Tip # 12. If you're frequently checking a prop's


value before doing something, introduce a new
component

❌ Bad: The code is cluttered because of all the user


== null checks.

Here, we can't return early because of the rules of


hooks.

function Posts({ user }) {


// Due to the rules of hooks, `posts` and
`handlePostSelect` must be declared before
the `if` statement.
const posts = useMemo(() => {
if (user == null) {
return [];
}
return getUserPosts(user.id);
}, [user]);

const handlePostSelect = useCallback(


(postId) => {
if (user == null) {
return;
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 28 / 140

}
// TODO: Do something
},
[user]
);

if (user == null) {
return null;
}

return (
<div>
{posts.map((post) => (
<button key={post.id} onClick={()
=> handlePostSelect(post.id)}>
{post.title}
</button>
))}
</div>
);
}

✅ Good: We introduce a new component, UserPosts ,


that takes a defined user and is much cleaner.

function Posts({ user }) {


if (user == null) {
return null;
}

return <UserPosts user={user} />;


}

function UserPosts({ user }) {


const posts = useMemo(() =>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 29 / 140

getUserPosts(user.id), [user.id]);

const handlePostSelect = useCallback(


(postId) => {
// TODO: Do something
},
[user]
);

return (
<div>
{posts.map((post) => (
<button key={post.id} onClick={()
=> handlePostSelect(post.id)}>
{post.title}
</button>
))}
</div>
);
}

➥ Tip # 13. Use the CSS :empty pseudo-class


to hide elements with no children

In the example below 👇


, a wrapper takes children and
adds a red border around them.

function PostWrapper({ children }) {


return <div className="posts-wrapper">
{children}</div>;
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 30 / 140

.posts-wrapper {
border: solid 1px red;
}

❌ Problem: The border remains visible on the screen


even if the children are empty (i.e., equal to null ,
undefined , etc.).

✅ Solution: Use the :empty CSS pseudo-class to


ensure the wrapper is not displayed when it's empty.

.posts-wrapper:empty {
display: none;
}

➥ Tip # 14. Group all the state and context at the


top of the component

When all the state and context are located at the top, it
is easy to spot what can trigger a component re-render.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 31 / 140

❌ Bad: State and context are scattered, making it hard


to track.

function App() {
const [email, setEmail] = useState("");
const onEmailChange = (event) => {
setEmail(event.target.value);
};
const [password, setPassword] =
useState("");
const onPasswordChange = (event) => {
setPassword(event.target.value);
};
const theme = useContext(ThemeContext);

return (
<div className={`App ${theme}`}>
<h1>Welcome</h1>
<p>
Email: <input type="email" value=
{email} onChange={onEmailChange} />
</p>
<p>
Password:{" "}
<input type="password" value=
{password} onChange={onPasswordChange} />
</p>
</div>
);
}

✅ Good: All state and context are grouped at the top,


making it easy to spot.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 32 / 140

function App() {
const theme = useContext(ThemeContext);
const [email, setEmail] = useState("");
const [password, setPassword] =
useState("");
const onEmailChange = (event) => {
setEmail(event.target.value);
};
const onPasswordChange = (event) => {
setPassword(event.target.value);
};

return (
<div className={`App ${theme}`}>
<h1>Welcome</h1>
<p>
Email: <input type="email" value=
{email} onChange={onEmailChange} />
</p>
<p>
Password:{" "}
<input type="password" value=
{password} onChange={onPasswordChange} />
</p>
</div>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 33 / 140

CATEGORY #2: EFFECTIVE DESIGN


PATTERNS & TECHNIQUES 🛠
➥ Tip # 15. Leverage the children props for
cleaner code (and performance benefits)

Using the children props has several benefits:

Benefit #1: You can avoid prop drilling by passing


props directly to children components instead of
routing them through the parent.
Benefit #2: Your code is more extensible since you
can easily modify children without changing the
parent component.
Benefit #3: You can use this trick to avoid re-
rendering "slow" components (see in the example
below 👇
).

❌ Bad: MyVerySlowComponent renders whenever


Dashboard renders, which happens every time the
current time updates.

💡 You can see it in action here, where I use React


Developer Tool's profiler.

function App() {
// Some other logic…
return <Dashboard />;
}

function Dashboard() {
const [currentTime, setCurrentTime] =
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 34 / 140

useState(new Date());
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(new Date());
}, 1_000);
return () => clearInterval(intervalId);
}, []);

return (
<>
<h1>{currentTime.toTimeString()}</h1>
<MyVerySlowComponent /> {/* Renders
whenever `Dashboard` renders */}
</>
);
}

✅ Good: MyVerySlowComponent doesn't render


when Dashboard renders.

function App() {
return (
<Dashboard>
<MyVerySlowComponent />
</Dashboard>
);
}

function Dashboard({ children }) {


const [currentTime, setCurrentTime] =
useState(new Date());
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(new Date());
}, 1_000);
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 35 / 140

return () => clearInterval(intervalId);


}, []);

return (
<>
<h1>{currentTime.toTimeString()}</h1>
{children}
</>
);
}

💡 You can see it in action here.

➥ Tip # 16. Build composable code with


compound components

Think of compound components as Lego blocks.

You piece them together to create a customized UI.


These components work exceptionally well when
creating libraries, resulting in both expressive and
highly extendable code.

You can explore this pattern further here 👉


Compound Pattern

Example from reach.ui (Menu, MenuButton, MenuList,


MenuLink are compound components)

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 36 / 140

<Menu>
<MenuButton>
Actions <span aria-hidden>▾</span>
</MenuButton>
<MenuList>
<MenuItem onSelect={() =>
alert("Download")}>Download</MenuItem>
<MenuItem onSelect={() =>
alert("Copy")}>Create a Copy</MenuItem>
<MenuLink as="a"
href="https://reacttraining.com/workshops/"
>
Attend a Workshop
</MenuLink>
</MenuList>
</Menu>

➥ Tip # 17. Make your code more extensible with


render functions or component
functions props

Let's say we want to display various lists, such as


messages, profiles, or posts, and each one should be
sortable.

To achieve this, we introduce a List component for


reuse. There are two ways we can go around this:

❌ Bad: Option 1 List handles rendering each item


and how they are sorted. This is problematic as it

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 37 / 140

violates the Open Closed Principle. Whenever a new item


type is added, this code will be modified.

✅ Good: Option 2 List takes render functions or


component functions, invoking them only when needed.

You can find an example in this sandbox below 👇:


🏖 https://codesandbox.io/p/sandbox/nice-
feistel-7yd768

➥ Tip # 18. When dealing with di erent cases,


use value === case && <Component />
to avoid holding onto old state

❌ Problem: In the sandbox below, the counter doesn't


reset when switching between Posts and Snippets .
This happens because when rendering the same
component, its state persists across type changes.

🏖 https://codesandbox.io/p/sandbox/counter-
zrl9pf

✅ Solution: Render a component based on the


selectedType or use a key to force a reset when the
type changes.

function App() {
const [selectedType, setSelectedType] =
useState < ResourceType > "posts";
return (
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 38 / 140

<>
<Navbar selectedType={selectedType}
onSelectType={setSelectedType} />
{selectedType === "posts" &&
<Resource type="posts" />}
{selectedType === "snippets" &&
<Resource type="snippets" />}
</>
);
}

// We use the `selectedType` as a key


function App() {
const [selectedType, setSelectedType] =
useState < ResourceType > "posts";
return (
<>
<Navbar selectedType={selectedType}
onSelectType={setSelectedType} />
<Resource type={selectedType} key=
{selectedType} />
</>
);
}

➥ Tip # 19. Always use error boundaries

By default, if your application encounters an error during


rendering, the entire UI crashes . 💥
To prevent this, use error boundaries to:

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 39 / 140

Keep parts of your app functional even if an error


occurs.
Display user-friendly error messages and
optionally track errors.

💡 Tip: you can use the react-error-boundary


library.

CATEGORY #3: KEYS & REFS 🗝


Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 40 / 140

➥ Tip # 20. Use crypto.randomUUID or


Math.random to generate keys

JSX elements inside a map() call always need keys.

Suppose your elements don't already have keys. In that


case, you can generate unique IDs using
crypto.randomUUID , Math.random , or the uuid
library.

Note: Beware that crypto.randomUUID is not


defined in older browsers.

➥ Tip # 21. Make sure your list items IDs are


stable (i.e., they don't change between renders)

As much as possible, keys/IDs should be stable.

Otherwise, React may re-render some components


uselessly, or selections will no longer be valid, like in the
example below.

❌ Bad: selectedQuoteId changes whenever App


renders, so there is never a valid selection.

function App() {
const [quotes, setQuotes] = useState([]);
const [selectedQuoteId,
setSelectedQuoteId] = useState(undefined);

// Fetch quotes

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 41 / 140

useEffect(() => {
const loadQuotes = () =>
fetchQuotes().then((result) => {
setQuotes(result);
});
loadQuotes();
}, []);

// Add ids: this is bad!!!


const quotesWithIds = quotes.map((quote)
=> ({
value: quote,
id: crypto.randomUUID(),
}));

return (
<List
items={quotesWithIds}
selectedItemId={selectedQuoteId}
onSelectItem={setSelectedQuoteId}
/>
);
}

✅ Good: The IDs are added when we get the quotes.


function App() {
const [quotes, setQuotes] = useState([]);
const [selectedQuoteId,
setSelectedQuoteId] = useState(undefined);

// Fetch quotes and save with ID


useEffect(() => {
const loadQuotes = () =>
fetchQuotes().then((result) => {
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 42 / 140

// We add the `ids` as soon as we


get the results
setQuotes(
result.map((quote) => ({
value: quote,
id: crypto.randomUUID(),
}))
);
});
loadQuotes();
}, []);

return (
<List
items={quotes}
selectedItemId={selectedQuoteId}
onSelectItem={setSelectedQuoteId}
/>
);
}

➥ Tip # 22. Strategically use the key attribute


to trigger component re-renders

Want to force a component to re-render from scratch?


Just change its key .

In the example below, we use this trick to reset the error


boundary when switching to a new tab.

🏖 Sandbox
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 43 / 140

➥ Tip # 23. Use a ref callback function


for tasks such as monitoring size changes and
managing multiple node elements.

Did you know you can pass a function to the ref


attribute instead of a ref object?

Here's how it works:

When the DOM node is added to the screen, React


calls the function with the DOM node as the
argument.
When the DOM node is removed, React calls the
function with null .

In the example below, we use this tip to skip the


useEffect

❌ Before: Using useEffect to focus the input


function App() {
const ref = useRef();

useEffect(() => {
ref.current?.focus();
}, []);

return <input ref={ref} type="text" />;


}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 44 / 140

✅ After: We focus on the input as soon as it is


available.

function App() {
const ref = useCallback((inputNode) => {
inputNode?.focus();
}, []);

return <input ref={ref} type="text" />;


}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 45 / 140

CATEGORY #4: ORGANIZING REACT


CODE 🧩
➥ Tip # 24. Colocate React components with
their assets (e.g., styles, images, etc.)

Always keep each React component with related assets,


like styles and images.

This makes it easier to remove them when the


component is no longer needed.
It also simplifies code navigation, as everything
you need is in one place.

➥ Tip # 25. Limit your component file size

Big files with tons of components and exports can be


confusing.
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 46 / 140

Plus, they tend to grow even bigger as more stuff gets


added.

So, aim for a reasonable file size and split components


into separate files when it makes sense.

➥ Tip # 26. Limit the number of return


statements in your functional component file

Multiple return statements in a functional


component make it hard to see what the component is
returning.

This was not a problem for class components where we


could search for the render term.

A handy trick is to use arrow functions without braces


when possible (VSCode has an action for this ). 😀
❌ Bad: It is harder to spot the component return
statement

function Dashboard({ posts, searchTerm,


onPostSelect }) {
const filteredPosts = posts.filter((post)
=> {
return post.title.includes(searchTerm);
});
const createPostSelectHandler = (post) =>
{
return () => {

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 47 / 140

onPostSelect(post.id);
};
};
return (
<>
<h1>Posts</h1>
<ul>
{filteredPosts.map((post) => {
return (
<li key={post.id} onClick=
{createPostSelectHandler(post)}>
{post.title}
</li>
);
})}
</ul>
</>
);
}

✅ Good: There is one return statement for the


component

function Dashboard({ posts, searchTerm,


onPostSelect, selectedPostId }) {
const filteredPosts = posts.filter((post)
=> post.title.includes(searchTerm));
const createPostSelectHandler = (post) =>
() => {
onPostSelect(post.id);
};
return (
<>
<h1>Posts</h1>
<ul>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 48 / 140

{filteredPosts.map((post) => (
<li
key={post.id}
onClick=
{createPostSelectHandler(post)}
style={{ color: post.id ===
selectedPostId ? "red" : "black" }}
>
{post.title}
</li>
))}
</ul>
</>
);
}

➥ Tip # 27. Prefer named exports over default


exports

I see default exports everywhere, and it makes me sad


🥲 .

Let's compare the two approaches:

/// `Dashboard` is exported as the default


component
export function Dashboard(props) {
/// TODO
}

/// `Dashboard` export is named

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 49 / 140

export function Dashboard(props) {


/// TODO
}

We now import the component like this:

/// Default export


import Dashboard from "/path/to/Dashboard";

/// Named export


import { Dashboard } from
"/path/to/Dashboard";

These are the problems with default exports:

If the component is renamed, the IDE won't


automatically rename the export.

For example, if Dashboard is renamed into Console ,


we will have this:

/// In the default export case, the name is


not changed
import Dashboard from "/path/to/Console";

/// In the named export case, the name is


changed
import { Console } from "/path/to/Console";

It's harder to see what is exported from a file with


default exports.
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 50 / 140

For example, in the case of named imports, once I type


import { } from "/path/to/file" , I get
autocompletion when I set my cursor inside the
brackets.

Default exports are harder to re-export.

For example, if I wanted to re-export the Dashboard


component from let's say an index file, I would have to
do this:

export { default as Dashboard } from


"/path/to/Dashboard";

The solution is more straightforward with named


exports.

export { Dashboard } from


"/path/to/Dashboard";

So, please default to named exports 🙏.


💡 Note: Even if you're using React lazy you can
still use named exports. See an example here.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 51 / 140

CATEGORY #5: EFFICIENT STATE


MANAGEMENT 🚦
➥ Tip # 28. Never create a state for a value that
can be derived from other state or props

More state = more trouble.

Every piece of state can trigger a re-render and make


resetting the state a hassle.

So, if a value can be derived from state or props, skip


adding a new state.

❌ Bad: filteredPosts doesn't need to be in the


state.

function App({ posts }) {


const [filters, setFilters] = useState();
const [filteredPosts, setFilteredPosts] =
useState([]);

useEffect(() => {
setFilteredPosts(filterPosts(posts,
filters));
}, [posts, filters]);

return (
<Dashboard>
<Filters filters={filters}
onFiltersChange={setFilters} />
{filteredPosts.length > 0 && <Posts
posts={filteredPosts} />}
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 52 / 140

</Dashboard>
);
}

✅ Good: filteredPosts is derived from posts


and filters.

function App({ posts }) {


const [filters, setFilters] =
useState({});
const filteredPosts = filterPosts(posts,
filters);

return (
<Dashboard>
<Filters filters={filters}
onFiltersChange={setFilters} />
{filteredPosts.length > 0 && <Posts
posts={filteredPosts} />}
</Dashboard>
);
}

➥ Tip # 29. Keep the state at the lowest level


necessary to minimize re-renders

Whenever the state changes inside a component, React


re-renders the component and all its children (there is
an exception with children wrapped in memo).

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 53 / 140

This happens even if those children don't use the


changed state. To minimize re-renders, move the state
down the component tree as far as possible.

❌ Bad: When sortOrder changes, both


LeftSidebar and RightSidebar re-render.

function App() {
const [sortOrder, setSortOrder] =
useState("popular");
return (
<div className="App">
<LeftSidebar />
<Main sortOrder={sortOrder}
setSortOrder={setSortOrder} />
<RightSidebar />
</div>
);
}

function Main({ sortOrder, setSortOrder })


{
return (
<div>
<Button
onClick={() =>
setSortOrder("popular")}
active={sortOrder === "popular"}
>
Popular
</Button>
<Button
onClick={() =>
setSortOrder("latest")}
active={sortOrder === "latest"}
>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 54 / 140

Latest
</Button>
</div>
);
}

✅ Good: sortOrder change will only affect Main .


function App() {
return (
<div className="App">
<LeftSidebar />
<Main />
<RightSidebar />
</div>
);
}

function Main() {
const [sortOrder, setSortOrder] =
useState("popular");
return (
<div>
<Button
onClick={() =>
setSortOrder("popular")}
active={sortOrder === "popular"}
>
Popular
</Button>
<Button
onClick={() =>
setSortOrder("latest")}
active={sortOrder === "latest"}
>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 55 / 140

Latest
</Button>
</div>
);
}

➥ Tip # 30. Clarify the distinction between the


initial state and the current state

❌ Bad: It's unclear that sortOrder is just the initial


value, which may lead to confusion or errors in state
management.

function Main({ sortOrder }) {


const [internalSortOrder,
setInternalSortOrder] =
useState(sortOrder);
return (
<div>
<Button
onClick={() =>
setInternalSortOrder("popular")}
active={internalSortOrder ===
"popular"}
>
Popular
</Button>
<Button
onClick={() =>
setInternalSortOrder("latest")}
active={internalSortOrder ===
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 56 / 140

"latest"}
>
Latest
</Button>
</div>
);
}

✅ Good: Naming is clear about what is the initial state


and what is current.

function Main({ initialSortOrder }) {


const [sortOrder, setSortOrder] =
useState(initialSortOrder);
return (
<div>
<Button
onClick={() =>
setSortOrder("popular")}
active={sortOrder === "popular"}
>
Popular
</Button>
<Button
onClick={() =>
setSortOrder("latest")}
active={sortOrder === "latest"}
>
Latest
</Button>
</div>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 57 / 140

➥ Tip # 31. Update state based on the previous


state, especially when memoizing with
useCallback

React allows you to pass an updater function to the


set function from useState .

This updater function uses the current state to calculate


the next state.

I use this behavior whenever I need to update the state


based on the previous state, especially inside functions
wrapped with useCallback. In fact, this approach
prevents the need to have the state as one of the hook
dependencies.

❌ Bad: handleAddTodo and handleRemoveTodo


change whenever todos changes.

function App() {
const [todos, setToDos] = useState([]);
const handleAddTodo = useCallback(
(todo) => {
setToDos([...todos, todo]);
},
[todos]
);

const handleRemoveTodo = useCallback(


(id) => {
setToDos(todos.filter((todo) =>
todo.id !== id));

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 58 / 140

},
[todos]
);

return (
<div className="App">
<TodoInput onAddTodo={handleAddTodo}
/>
<TodoList todos={todos} onRemoveTodo=
{handleRemoveTodo} />
</div>
);
}

✅ Good: handleAddTodo and handleRemoveTodo


remain the same even when todos changes.

function App() {
const [todos, setToDos] = useState([]);
const handleAddTodo = useCallback((todo)
=> {
setToDos((prevTodos) => [...prevTodos,
todo]);
}, []);

const handleRemoveTodo = useCallback((id)


=> {
setToDos((prevTodos) =>
prevTodos.filter((todo) => todo.id !==
id));
}, []);

return (
<div className="App">
<TodoInput onAddTodo={handleAddTodo}
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 59 / 140

/>
<TodoList todos={todos} onRemoveTodo=
{handleRemoveTodo} />
</div>
);
}

➥ Tip # 32. Use functions in useState for lazy


initialization and performance gains, as they are
invoked only once.

Using a function in useState ensures the initial state is


computed only once.

This can improve performance, especially when the


initial state is derived from an "expensive" operation like
reading from local storage.

❌ Bad: We read the theme from local storage every


time the component renders

const THEME_LOCAL_STORAGE_KEY = "101-react-


tips-theme";

function PageWrapper({ children }) {


const [theme, setTheme] = useState(

localStorage.getItem(THEME_LOCAL_STORAGE_KE
Y) || "dark"
);

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 60 / 140

const handleThemeChange = (theme) => {


setTheme(theme);

localStorage.setItem(THEME_LOCAL_STORAGE_KE
Y, theme);
};

return (
<div
className="page-wrapper"
style={{ background: theme === "dark"
? "black" : "white" }}
>
<div className="header">
<button onClick={() =>
handleThemeChange("dark")}>Dark</button>
<button onClick={() =>
handleThemeChange("light")}>Light</button>
</div>
<div>{children}</div>
</div>
);
}

✅ Good: We only read from the local storage when the


component mounts.

function PageWrapper({ children }) {


const [theme, setTheme] = useState(
() =>
localStorage.getItem(THEME_LOCAL_STORAGE_KE
Y) || "dark"
);

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 61 / 140

const handleThemeChange = (theme) => {


setTheme(theme);

localStorage.setItem(THEME_LOCAL_STORAGE_KE
Y, theme);
};

return (
<div
className="page-wrapper"
style={{ background: theme === "dark"
? "black" : "white" }}
>
<div className="header">
<button onClick={() =>
handleThemeChange("dark")}>Dark</button>
<button onClick={() =>
handleThemeChange("light")}>Light</button>
</div>
<div>{children}</div>
</div>
);
}

➥ Tip # 33. Use react context for broadly


needed, static state to prevent prop drilling

I will use React context whenever I have some data that:

Is needed in multiple places (e.g., theme, current


user, etc.)

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 62 / 140

Is mostly static or read-only (i.e., the user


can't/doesn't change the data often)

This approach helps avoid prop drilling (i.e., passing


down data or state through multiple layers of the
component hierarchy).

See an example in the sandbox below 👇.


🏖 https://codesandbox.io/p/sandbox/sad-farrell-
t4cqqp

➥ Tip # 34. React Context: Split your context


into parts that change frequently and those that
change infrequently to enhance app
performance

One challenge with React context is that all components


consuming the context re-render whenever the context
data changes, even if they don't use the part of the
context that changed .

A solution? Use separate contexts.

In the example below, we've created two contexts: one for


actions (which are constant) and another for state
(which can change).

🏖 https://codesandbox.io/p/sandbox/context-
split-vdny3w

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 63 / 140

➥ Tip # 35. React Context: Introduce a


Provider component when the value
computation is not straightforward

❌ Bad: There is too much logic inside App to manage


the theme.

const THEME_LOCAL_STORAGE_KEY = "101-react-


tips-theme";
const DEFAULT_THEME = "light";

const ThemeContext = createContext({


theme: DEFAULT_THEME,
setTheme: () => null,
});

function App() {
const [theme, setTheme] = useState(
() =>
localStorage.getItem(THEME_LOCAL_STORAGE_KE
Y) || DEFAULT_THEME
);
useEffect(() => {
if (theme !== "system") {
updateRootElementTheme(theme);
return;
}

// We need to get the class to apply


based on the system theme
const systemTheme = window.matchMedia("
(prefers-color-scheme: dark)")
.matches

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 64 / 140

? "dark"
: "light";

updateRootElementTheme(systemTheme);

// Then watch for changes in the system


theme and update the root element
accordingly
const darkThemeMq = window.matchMedia("
(prefers-color-scheme: dark)");
const listener = (event) => {
updateRootElementTheme(event.matches
? "dark" : "light");
};
darkThemeMq.addEventListener("change",
listener);
return () =>
darkThemeMq.removeEventListener("change",
listener);
}, [theme]);

const themeContextValue = {
theme,
setTheme: (theme) => {

localStorage.setItem(THEME_LOCAL_STORAGE_KE
Y, theme);
setTheme(theme);
},
};

const [selectedPostId, setSelectedPostId]


= useState(undefined);
const onPostSelect = (postId) => {
// TODO: some logging
setSelectedPostId(postId);
};

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 65 / 140

const posts = useSWR("/api/posts",


fetcher);

return (
<div className="App">
<ThemeContext.Provider value=
{themeContextValue}>
<Dashboard
posts={posts}
onPostSelect={onPostSelect}
selectedPostId={selectedPostId}
/>
</ThemeContext.Provider>
</div>
);
}

✅ Good: The theme logic is encapsulated in


ThemeProvider

function App() {
const [selectedPostId, setSelectedPostId]
= useState(undefined);
const onPostSelect = (postId) => {
// TODO: some logging
setSelectedPostId(postId);
};

const posts = useSWR("/api/posts",


fetcher);

return (
<div className="App">
<ThemeProvider>
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 66 / 140

<Dashboard
posts={posts}
onPostSelect={onPostSelect}
selectedPostId={selectedPostId}
/>
</ThemeProvider>
</div>
);
}

function ThemeProvider({ children }) {


const [theme, setTheme] = useState(
() =>
localStorage.getItem(THEME_LOCAL_STORAGE_KE
Y) || DEFAULT_THEME
);
useEffect(() => {
if (theme !== "system") {
updateRootElementTheme(theme);
return;
}

// We need to get the class to apply


based on the system theme
const systemTheme = window.matchMedia("
(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";

updateRootElementTheme(systemTheme);

// Then watch for changes in the system


theme and update the root element
accordingly
const darkThemeMq = window.matchMedia("
(prefers-color-scheme: dark)");

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 67 / 140

const listener = (event) => {


updateRootElementTheme(event.matches
? "dark" : "light");
};
darkThemeMq.addEventListener("change",
listener);
return () =>
darkThemeMq.removeEventListener("change",
listener);
}, [theme]);

const themeContextValue = {
theme,
setTheme: (theme) => {

localStorage.setItem(THEME_LOCAL_STORAGE_KE
Y, theme);
setTheme(theme);
},
};

return (
<div className="App">
<ThemeContext.Provider value=
{themeContextValue}>
{children}
</ThemeContext.Provider>
</div>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 68 / 140

➥ Tip # 36. Consider using the useReducer


hook as a lightweight state management solution

Whenever I have too many values in my state or a


complex state and don't want to rely on external
libraries, I will reach for useReducer .

It's especially effective when combined with context for


broader state management needs.

Example: See #Tip 34.

➥ Tip # 37. Simplify state updates with


useImmer or useImmerReducer

With hooks like useState and useReducer , the


state must be immutable (i.e., all changes need to create
a new state vs. modifying the current one).

This is often cumbersome to achieve.

This is where useImmer and useImmerReducer offer a


simpler alternative. They allow you to write "mutable"
code automatically converted to immutable updates.

❌ Tedious: We must carefully ensure we're creating a


new state object.

export function App() {


const [{ email, password }, setState] =
useState({
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 69 / 140

email: "",
password: "",
});
const onEmailChange = (event) => {
setState((prevState) => ({
...prevState, email: event.target.value
}));
};
const onPasswordChange = (event) => {
setState((prevState) => ({
...prevState, password: event.target.value
}));
};

return (
<div className="App">
<h1>Welcome</h1>
<p>
Email: <input type="email" value=
{email} onChange={onEmailChange} />
</p>
<p>
Password:{" "}
<input type="password" value=
{password} onChange={onPasswordChange} />
</p>
</div>
);
}

✅ More straightforward: We can directly modify


draftState .

import { useImmer } from "use-immer";

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 70 / 140

export function App() {


const [{ email, password }, setState] =
useImmer({
email: "",
password: "",
});
const onEmailChange = (event) => {
setState((draftState) => {
draftState.email =
event.target.value;
});
};
const onPasswordChange = (event) => {
setState((draftState) => {
draftState.password =
event.target.value;
});
};

/// Rest of logic


}

➥ Tip # 38. Use Redux (or another state


management solution) for complex client-side
state accessed across multiple components

I turn to Redux whenever:

I have a complex FE app with a lot of shared client-


side state (for example, dashboard apps)
I want the user to be able to go back in time and
revert changes
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 71 / 140

I don't want my components to re-render


unnecessarily like they can with React context
I have too many contexts that start getting out of
control

For a streamlined experience, I recommend using redux-


tooltkit.

💡 Note: You can also consider other alternatives


to Redux, such as Zustand or Recoil.

➥ Tip # 39. Redux: Use Redux DevTools to


debug your state

The Redux DevTools browser extension is an useful tool


for debugging your Redux projects.

It allows you to visualize your state and actions in real-


time, maintain state persistence across refreshes, and
much more.

To understand its use, watch this great YouTube video.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 72 / 140

CATEGORY #6: REACT CODE


OPTIMIZATION 🚀
➥ Tip # 40. Prevent unnecessary re-renders
with memo

When dealing with components that are costly to render


and their parent components frequently update,
wrapping them in memo can be a game changer.

memo ensures that a component only re-renders when


its props have changed, not simply because its parent
re-rendered.

In the example below, I get some data from the server


through useGetDashboardData . If the posts didn't
change, wrapping ExpensiveList in memo will
prevent it from re-rendering when other parts of the data
update.

export function App() {


const { profileInfo, posts } =
useGetDashboardData();
return (
<div className="App">
<h1>Dashboard</h1>
<Profile data={profileInfo} />
<ExpensiveList posts={posts} />
</div>
);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 73 / 140

const ExpensiveList = memo(({ posts }) => {


/// Rest of implementation
});

💡 : This tip may be irrelevant once React compiler


gets stable 😅 .

➥ Tip # 41. Specify an equality function with


memo to instruct React on how to compare the
props.

By default, memo uses Object.is to compare each prop


with its previous value.

However, specifying a custom equality function can be


more efficient than default comparisons or re-rendering
for more complex or specific scenarios.

Example 👇
const ExpensiveList = memo(
({ posts }) => {
return <div>{JSON.stringify(posts)}
</div>;
},
(prevProps, nextProps) => {
// Only re-render if the last post or
the list size changes
const prevLastPost =
prevProps.posts[prevProps.posts.length -

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 74 / 140

1];
const nextLastPost =
nextProps.posts[nextProps.posts.length -
1];
return (
prevLastPost.id === nextLastPost.id
&&
prevProps.posts.length ===
nextProps.posts.length
);
}
);

➥ Tip # 42. Prefer named functions over arrow


functions when declaring a memoized
component

When defining memoized components, using named


functions instead of arrow functions can improve clarity
in React DevTools.

Arrow functions often result in generic names like _c2 ,


making debugging and profiling more difficult.

❌ Bad: Using arrow functions for memoized


components results in less informative names in React
DevTools.

const ExpensiveList = memo(({ posts }) => {


/// Rest of implementation

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 75 / 140

});

ExpensiveList name is not visible

✅ Good: The component's name will be visible in


DevTools.

const ExpensiveList = memo(function


ExpensiveListFn({ posts }) {
/// Rest of implementation
});

You can see ExpensiveListFn in DevTools

➥ Tip # 43. Cache expensive computations or


preserve references with useMemo

I will generally useMemo :

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 76 / 140

When I have expensive computations that should


not be repeated on each render.
If the computed value is a non-primitive value
that is used as a dependency in hooks like
useEffect .
The computed non-primitive value will be passed
as a prop to a component wrapped in memo ;
otherwise, this will break the memoization since
React uses Object.is to detect whether props
changed.

❌ Bad: The memo for ExpensiveList does not


prevent re-renders because styles are recreated on every
render.

export function App() {


const { profileInfo, posts, baseStyles }
= useGetDashboardData();
// We get a new `styles` object on every
render
const styles = { ...baseStyles, padding:
"10px" };
return (
<div className="App">
<h1>Dashboard</h1>
<Profile data={profileInfo} />
<ExpensiveList posts={posts} styles=
{styles} />
</div>
);
}

const ExpensiveList = memo(function


ExpensiveListFn({ posts, styles }) {

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 77 / 140

/// Rest of implementation


});

✅ Good: The use of useMemo ensures styles only


changes when baseStyles changes, allowing memo
to effectively prevent unnecessary re-renders.

export function App() {


const { profileInfo, posts, baseStyles }
= useGetDashboardData();
// We get a new `styles` object only if
`baseStyles` changes
const styles = useMemo(
() => ({ ...baseStyles, padding: "10px"
}),
[baseStyles]
);
return (
<div className="App">
<h1>Dashboard</h1>
<Profile data={profileInfo} />
<ExpensiveList posts={posts} styles=
{styles} />
</div>
);
}

➥ Tip # 44. Use useCallback to memoize


functions

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 78 / 140

useCallback is similar to useMemo but is designed


explicitly for memoizing functions.

❌ Bad: Whenever the theme changes,


handleThemeChange will be called twice, and we will
push logs to the server twice.

function useTheme() {
const [theme, setTheme] =
useState("light");

// `handleThemeChange` changes on every


render
// As a result, the effect will be
triggered after each render
const handleThemeChange = (newTheme) => {
pushLog(["Theme changed"], {
context: {
theme: newTheme,
},
});
setTheme(newTheme);
};

useEffect(() => {
const dqMediaQuery =
window.matchMedia("(prefers-color-scheme:
dark)");
handleThemeChange(dqMediaQuery.matches
? "dark" : "light");
const listener = (event) => {
handleThemeChange(event.matches ?
"dark" : "light");
};
dqMediaQuery.addEventListener("change",
listener);
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 79 / 140

return () => {

dqMediaQuery.removeEventListener("change",
listener);
};
}, [handleThemeChange]);

return theme;
}

✅ Good: Wrapping handleThemeChange in


useCallback ensures that it is recreated only when
necessary, reducing unnecessary executions.

const handleThemeChange =
useCallback((newTheme) => {
pushLog(["Theme changed"], {
context: {
theme: newTheme,
},
});
setTheme(newTheme);
}, []);

➥ Tip # 45. Memoize callbacks or values


returned from utility hooks to avoid performance
issues

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 80 / 140

When you create a custom hook to share with others,


memoizing the returned values and functions is crucial.

This practice makes your hook more efficient and


prevents unnecessary performance issues for anyone
using it.

❌ Bad: loadData is not memoized and creates


performance issues.

function useLoadData(fetchData) {
const [result, setResult] = useState({
type: "notStarted",
});

async function loadData() {


setResult({ type: "loading" });
try {
const data = await fetchData();
setResult({ type: "loaded", data });
} catch (err) {
setResult({ type: "error", error: err
});
}
}

return { result, loadData };


}

✅ Good: We memoize everything so there are no


unexpected performance issues.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 81 / 140

function useLoadData(fetchData) {
const [result, setResult] = useState({
type: "notStarted",
});

// Wrap in `useRef` and use the `ref`


value so the function never changes
const fetchDataRef = useRef(fetchData);
useEffect(() => {
fetchDataRef.current = fetchData;
}, [fetchData]);

// Wrap in `useCallback` and use the


`ref` value so the function never changes
const loadData = useCallback(async () =>
{
setResult({ type: "loading" });
try {
const data = await
fetchDataRef.current();
setResult({ type: "loaded", data });
} catch (err) {
setResult({ type: "error", error: err
});
}
}, []);

return useMemo(() => ({ result, loadData


}), [result, loadData]);
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 82 / 140

➥ Tip # 46. Leverage lazy loading and


Suspense to make your apps load faster

When you're building your app, consider using lazy


loading and Suspense for code that is:

Expensive to load.
Only relevant to some users (like premium
features).
Not immediately necessary for the initial user
interaction.

In the sandbox below 👇


, the Slider assets (JS + CSS)
only load after you click on a card.

🏖 https://stackblitz.com/edit/vitejs-vite-czefdj?
file=src%2FApp.jsx

Slider assets only load when needed

➥ Tip # 47. Throttle your network to simulate a


slow network
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 83 / 140

Did you know you can simulate slow internet


connections directly in Chrome?

This is especially useful when:

Customers report slow loading times that you can't


replicate on your faster network.
You're implementing lazy loading and want to
observe how files load under slower conditions to
ensure appropriate loading states.

💡 Find out how to do it on this link.

➥ Tip # 48. Use react-window or react-


virtuoso to e ciently render lists

Never render a long list of items all at once—such as


chat messages, logs, or infinite lists.

Doing so can cause the browser to freeze.

Instead, virtualize the list. This means rendering only the


subset of items likely to be visible to the user.

Libraries like react-window, react-virtuoso or


@tanstack/react-virtual are designed for this purpose.

❌ Bad: NonVirtualList renders all 50,000 log lines


simultaneously, even if they aren't visible.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 84 / 140

function NonVirtualList({ items }) {


return (
<div style={{ height: "100%" }}>
{items.map((log, index) => (
<div
key={log.id}
style={{
padding: "5px",
borderBottom:
index === items.length - 1 ?
"none" : "1px solid #ccc",
}}
>
<LogLine log={log} index={index}
/>
</div>
))}
</div>
);
}

✅ Good: VirtualList renders only the items likely


to be visible.

function VirtualList({ items }) {


return (
<Virtuoso
style={{ height: "100%" }}
data={items}
itemContent={(index, log) => (
<div
key={log.id}
style={{
padding: "5px",
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 85 / 140

borderBottom:
index === items.length - 1 ?
"none" : "1px solid #ccc",
}}
>
<LogLine log={log} index={index}
/>
</div>
)}
/>
);
}

You can switch between the two options in the sandbox


below and notice how bad the app performs when
NonVirtualList is used . 👇
🏖 https://codesandbox.io/p/sandbox/virtual-list-
9qfh5y

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 86 / 140

CATEGORY #7: DEBUGGING REACT


CODE 🐞
➥ Tip # 49. Use StrictMode to catch bugs in
your components before deploying them to
production

Using StrictMode is a proactive way to detect potential


issues in your application during development.

It helps identify problems such as:

Incomplete cleanup in effects, like forgetting to


release resources.
Impurities in React components, ensuring they
return consistent JSX given the same inputs
(props, state, and context).

The example below shows a bug because


clearInterval is never called. StrictMode helps
catch this by running the effect twice, which creates two
intervals.

🏖 https://codesandbox.io/p/sandbox/strict-
mode-example-pyrcg8

➥ Tip # 50. Install the React Developer Tools


browser extension to view/edit your components
and detect performance issues
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 87 / 140

React Developer Tools is a must extension (Chrome,


Firefox).

This extension lets you:

Visualize and delve into the details of your React


components, examining everything from props to
state.
Directly modify a component's state or props to see
how changes affect behavior and rendering.
Profile your application to identify when and why
components are re-rendering, helping you spot
performance issues.
Etc.

💡 Learn how to use it in this great guide.

➥ Tip # 51. React DevTools Components:


Highlight components that render to identify
potential issues

I will use this trick whenever I suspect that my app has


performance issues. You can highlight the components
that render to detect potential problems (e.g., too many
renders).

The gif below shows that the FollowersListFn


component re-renders whenever the time changes,
which is wrong.

💡 You can see it in action on this link.


Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 88 / 140

➥ Tip # 52. Leverage useDebugValue in your


custom hooks for better visibility in React
DevTools

useDebugValue can be a handy tool for adding


descriptive labels to your custom hooks in React
DevTools.

This makes it easier to monitor their states directly from


the DevTools interface.

For instance, consider this custom hook I use to fetch


and display the current time, updated every second:

function useCurrentTime() {
const [time, setTime] = useState(new
Date());

useEffect(() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 1_000);
return () => clearInterval(intervalId);
}, [setTime]);

return time;
}

❌ Bad: Without useDebugValue , the actual time


value isn't immediately visible; you'd need to expand the
CurrentTime hook:
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 89 / 140

Current time not quickly visible on the


devtools

✅ Good: With useDebugValue , the current time is


readily visible:

useDebugValue(time);

Current time quickly visible on the devtools

Note: Use useDebugValue judiciously. It's best


reserved for complex hooks in shared libraries
where understanding the internal state is crucial.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 90 / 140

➥ Tip # 53. Use the why-did-you-render


library to track component rendering and identify
potential performance bottlenecks

Sometimes, a component re-renders, and it's not


immediately clear why .

While React DevTools is helpful, in large apps, it might


only provide vague explanations like "hook #1 rendered,"
which can be useless.

App rendering because of hook 1 change

In such cases, you can turn to the why-did-you-render


library. It offers more detailed insights into why
components re-render, helping to pinpoint performance
issues more effectively.

I made an example in the sandbox below 👇 . Thanks to


this library, we can find the issue with the
FollowersList component.

🏖 https://codesandbox.io/p/sandbox/why-did-
you-render-sandbox-forked-nc4fnk

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 91 / 140

why-did-you-render console logs

➥ Tip # 54. Hide logs during the second render


in Strict Mode

StrictMode helps catch bugs early in your application's


development.

However, since it causes components to render twice,


this can result in duplicated logs, which might clutter
your console.

You can hide logs during the second render in Strict


Mode to address this.

Check out how to do it in the gif below 👇:


💡 Hide logs during the second render in Strict
Mode

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 92 / 140

CATEGORY #8: TESTING REACT


CODE 🧪
➥ Tip # 55. Use React Testing Library to
test your React components e ectively

Want to test your React apps?

Make sure to use @testing-library/react.

You can find a minimal example here.

➥ Tip # 56. React Testing Library: Use testing


playground to e ortlessly create queries

Struggling to decide which queries to use in your tests?

Consider using testing playground to quickly generate


them from your component's HTML.

Here are two ways to leverage it:

Option #1: Use


screen.logTestingPlaygroundURL() in your test.
This function generates a URL that opens the Testing
Playground tool with the HTML of your component
already loaded.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 93 / 140

Option #2: Install Testing Playground Chrome extension.


This extension allows you to hover over elements in your
app directly in the browser to find the best queries for
testing them.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 94 / 140

➥ Tip # 57. Conduct end-to-end tests with


Cypress or Playwright

Need to conduct end-to-end tests?

Make sure to check out Cypress or Playwright.

Note: Playwright's support for components is


experimental at the time of writing.

➥ Tip # 58. Use MSW to mock network requests


in your tests

Sometimes, your tests need to make network requests.

Rather than implementing your own mocks (or, God


forbid, making actual network requests ), consider 😅
using MSW (Mock Service Worker) to handle your API
responses.

MSW allows you to intercept and manipulate network


interactions directly in your tests, providing a robust
and straightforward solution for simulating server
responses without affecting live servers.

This approach helps maintain a controlled and


predictable testing environment, enhancing the
reliability of your tests.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 95 / 140

CATEGORY #9: REACT HOOKS 🎣


➥ Tip # 59. Make sure you perform any required
cleanup in your useEffect hooks

Always return a cleanup function in your useEffect


hooks if you're setting up anything that needs to be
cleaned up later.

This could be anything from ending a chat session to


closing a database connection.

Neglecting this step can lead to poor resource usage and


potential memory leaks.

❌ Bad: This example sets an interval. But we never


clear it, which means it keeps running even after the
component is unmounted.

function Timer() {
const [time, setTime] = useState(new
Date());
useEffect(() => {
setInterval(() => {
setTime(new Date());
}, 1_000);
}, []);

return <>Current time


{time.toLocaleTimeString()}</>;
}

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 96 / 140

✅ Good: The interval is properly cleared when the


component unmounts.

function Timer() {
const [time, setTime] = useState(new
Date());
useEffect(() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 1_000);
// We clear the interval
return () => clearInterval(intervalId);
}, []);

return <>Current time


{time.toLocaleTimeString()}</>;
}

➥ Tip # 60. Use refs for accessing DOM


elements

You should never manipulate the DOM directly with


React.

Methods like document.getElementById and


document.getElementsByClassName are forbidden
since React should access/manipulate the DOM.

So, what should you do when you need access to DOM


elements?

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 97 / 140

You can use the useRef hook, like in the example below,
where we need access to the canvas element.

🏖 https://codesandbox.io/p/sandbox/chart-js-
example-xdrnqv

Note: We could have added an ID to the canvas and


used document.getElementById , but this is
not recommended.

➥ Tip # 61. Use refs to preserve values


across re-renders

If you have mutable values in your React component


that aren't stored in the state, you'll notice that changes
to these values don't persist through re-renders.

This happens unless you save them globally.

You might consider putting these values in the state.


However, if they are irrelevant to the rendering, doing so
can cause unnecessary re-renders, which wastes
performance.

This is where useRef also shines.

In the example below, I want to stop the timer when the


user clicks on some button. For that, I need to store the
intervalId somewhere.

❌ Bad: The example below won't work as intended


because intervalId gets reset with every component
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 98 / 140

re-render.

function Timer() {
const [time, setTime] = useState(new
Date());
let intervalId;

useEffect(() => {
intervalId = setInterval(() => {
setTime(new Date());
}, 1_000);
return () => clearInterval(intervalId);
}, []);

const stopTimer = () => {


intervalId &&
clearInterval(intervalId);
};

return (
<>
<>Current time:
{time.toLocaleTimeString()} </>
<button onClick={stopTimer}>Stop
timer</button>
</>
);
}

✅ Good: By using useRef , we ensure that the interval


ID is preserved between renders.

function Timer() {
const [time, setTime] = useState(new
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 99 / 140

Date());
const intervalIdRef = useRef();
const intervalId = intervalIdRef.current;

useEffect(() => {
const interval = setInterval(() => {
setTime(new Date());
}, 1_000);
intervalIdRef.current = interval;
return () => clearInterval(interval);
}, []);

const stopTimer = () => {


intervalId &&
clearInterval(intervalId);
};

return (
<>
<>Current time:
{time.toLocaleTimeString()} </>
<button onClick={stopTimer}>Stop
timer</button>
</>
);
}

➥ Tip # 62. Prefer named functions over arrow


functions within hooks such as useEffect to
easily find them in React Dev Tools

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 100 / 140

If you have many hooks, finding them in React DevTools


can be challenging.

One trick is to use named functions so you can quickly


spot them.

❌ Bad: It's hard to find the specific effect among many


hooks.

function HelloWorld() {
useEffect(() => {
console.log(" 🚀
~ Hello, I just got
mounted");
}, []);

return <>Hello World</>;


}

Effect has no associated name

✅ Good: You can quickly spot the effect.


function HelloWorld() {
useEffect(function logOnMount() {
console.log(" 🚀
~ Hello, I just got
mounted");
}, []);

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 101 / 140

return <>Hello World</>;


}

Effect with associated name

➥ Tip # 63. Encapsulate logic with custom hooks

Let's say I have a component that gets the theme from


the user's dark mode preferences and uses it inside the
app.

It's better to extract the logic that returns the theme into
a custom hook (to reuse it and keep the component
clean).

❌ Bad: App is overcrowded


function App() {
const [theme, setTheme] =
useState("light");

useEffect(() => {
const dqMediaQuery =
window.matchMedia("(prefers-color-scheme:
dark)");
setTheme(dqMediaQuery.matches ? "dark"
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 102 / 140

: "light");
const listener = (event) => {
setTheme(event.matches ? "dark" :
"light");
};
dqMediaQuery.addEventListener("change",
listener);
return () => {

dqMediaQuery.removeEventListener("change",
listener);
};
}, []);

return (
<div className={`App ${theme === "dark"
? "dark" : ""}`}>Hello Word</div>
);
}

✅ Good: App is much simpler, and we can reuse the


logic

function App() {
const theme = useTheme();

return (
<div className={`App ${theme === "dark"
? "dark" : ""}`}>Hello Word</div>
);
}

// Custom hook that can be reused


function useTheme() {
const [theme, setTheme] =
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 103 / 140

useState("light");

useEffect(() => {
const dqMediaQuery =
window.matchMedia("(prefers-color-scheme:
dark)");
setTheme(dqMediaQuery.matches ? "dark"
: "light");
const listener = (event) => {
setTheme(event.matches ? "dark" :
"light");
};
dqMediaQuery.addEventListener("change",
listener);
return () => {

dqMediaQuery.removeEventListener("change",
listener);
};
}, []);

return theme;
}

➥ Tip # 64. Prefer functions over custom hooks

Never put logic inside a hook when a function can be


used 🛑
.

In effect:

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 104 / 140

Hooks can only be used inside other hooks or


components, whereas functions can be used
everywhere.
Functions are simpler than hooks.
Functions are easier to test.
Etc.

❌ Bad: The useLocale hook is unnecessary since it


doesn't need to be a hook. It doesn't use other hooks like
useEffect , useState , etc.

function App() {
const locale = useLocale();
return (
<div className="App">
<IntlProvider locale={locale}>
<BlogPost post={EXAMPLE_POST} />
</IntlProvider>
</div>
);
}

function useLocale() {
return window.navigator.languages?.[0] ??
window.navigator.language;
}

✅ Good: Create a function getLocale instead


function App() {
const locale = getLocale();
return (
<div className="App">
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 105 / 140

<IntlProvider locale={locale}>
<BlogPost post={EXAMPLE_POST} />
</IntlProvider>
</div>
);
}

function getLocale() {
return window.navigator.languages?.[0] ??
window.navigator.language;
}

➥ Tip # 65. Prevent visual UI glitches by using


the useLayoutEffect hook

When an effect isn't caused by a user interaction, the


user will see the UI before the effect runs (often briefly).

As a result, if the effect modifies the UI, the user will see
the initial UI version very quickly before seeing the
updated one, creating a visual glitch.

Using useLayoutEffect ensures the effect runs


synchronously after all DOM mutations, preventing the
initial render glitch.

In the sandbox below, we want the width to be equally


distributed between the columns (I know this can be
done in CSS, but I need an example ). 😅

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 106 / 140

With useEffect , you can see briefly at the beginning


that the table is changing. The columns are rendered
with their default size before being adjusted to their
correct size.

🏖 https://codesandbox.io/p/sandbox/use-
layout-effect-hqhnld

If you're looking for another great usage, check out this


post.

➥ Tip # 66. Generate unique IDs for


accessibility attributes with the useId hook

Tired of coming up with IDs or having them clash?

You can use the useId hook to generate a unique ID


inside your React component and ensure your app is
accessible.

Example

function Form() {
const id = useId();
return (
<div className="App">
<div>
<label>
Name <input type="text" aria-
describedby={id} />
</label>

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 107 / 140

</div>
<span id={id}>Make sure to include
full name</span>
</div>
);
}

➥ Tip # 67. Use the useSyncExternalStore


to subscribe to an external store

This is a rarely needed but super powerful hook 💪.


Use this hook if:

You have some state not accessible in the React


tree (i.e., not present in the state or context)
The state can change, and you need your
component to be notified of changes

In the example below, I want a Logger singleton to log


errors, warnings, info, etc., in my entire app.

These are the requirements:

I need to be able to call this everywhere in my React


app (even inside non-React components), so I
won't put it inside a state/context.
I want to display all the logs to the user inside a
Logs component

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 108 / 140

👉 I can use useSyncExternalStore inside my


Logs component to access the logs and listen to
changes.

function createLogger() {
let logs = [];
let listeners = [];

const pushLog = (log) => {


logs = [...logs, log];
listeners.forEach((listener) =>
listener());
};

return {
getLogs: () => Object.freeze(logs),
subscribe: (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter((l) =>
l !== listener);
};
},
info: (message) => {
pushLog({ level: "info", message });
console.info(message);
},
error: (message) => {
pushLog({ level: "error", message });
console.error(message);
},
warn: (message) => {
pushLog({ level: "warn", message });
console.warn(message);
},
};
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 109 / 140

export const Logger = createLogger();

🏖 https://codesandbox.io/p/sandbox/sync-
external-storage-rkq2zq

➥ Tip # 68. Use the useDeferredValue hook


to display the previous query results until the
new results become available

Imagine you're building an app that represents countries


on a map.

Users can filter to see countries up to a specific


population size.

Every time maxPopulationSize updates, the map is


re-rendered (see sandbox below).

🏖 https://codesandbox.io/p/sandbox/countries-
app-use-deferred-value-4nh73p

As a result, notice how janky the slider is when you


move it too fast. This is because the map is re-rendered
every time the slider moves.

To solve this, we can use the useDeferredValue hook


so that the slider updates smoothly.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 110 / 140

<Map
maxPopulationSize=
{deferredMaxPopulationSize}
// …
/>

If you're looking for another great usage, check out this


post.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 111 / 140

CATEGORY #10: MUST-KNOWN


REACT LIBRARIES/TOOLS 🧰
➥ Tip # 69. Incorporate routing into your app
with react-router

If you need your app to support multiple pages, check


out react-router.

You can find a minimal example here.

➥ Tip # 70. Implement first-class data fetching in


your app with swr or React Query

Data fetching can be notoriously tricky.

However, libraries like swr or React Query make it much


easier.

I recommend swr for simple use cases and React Query


for more complex ones.

➥ Tip # 71. Simplify form state management with


libraries like formik , React Hook Form , or
TanStack Form

I used to hate form management in React 🥲.


Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 112 / 140

That was until I discovered libraries like:

formik
React Hook Form, or
or TanStack Form

So make sure to check these out if you're struggling with


forms.

➥ Tip # 72. Internationalize your app using


Format.js, Lingui, or react-i18next.

If your app needs to support multiple languages, it


should be internationalized.

You can achieve this with libraries like:

Format.js
Lingui
react-i18next

➥ Tip # 73. E ortlessly create impressive


animations with framer-motion

Animations can make your app stand out 🔥.


You can create them easily with framer-motion.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 113 / 140

➥ Tip # 74. Tired of re-inventing the wheel with


custom hooks? Check out https://usehooks.com/

If you're like me, you've written the same hooks over and
over again.

So check usehooks.com first to see if someone has


already done the work for you.

➥ Tip # 75. Streamline app development by


leveraging UI libraries like Shadcdn or Headless
UI

It's hard to build UI at scale that is accessible,


responsive, and beautiful.

Libraries like Shadcdn or Headless UI make it easier.

Shadcdn provides a set of accessible, reusable,


and composable React components that you can
copy and paste into your apps. At the time of
writing, it requires Tailwind CSS.

Headless UI provides unstyled, fully accessible UI


components that you can use to build your own UI
components.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 114 / 140

➥ Tip # 76. Check your website's accessibility


with the axe-core-npm library

Websites should be accessible to everyone.

However, it's easy to miss accessibility issues.

axe-core-npm is a fast, secure, and reliable way to check


your website's accessibility while developing it.

💡 Tip: If you're a VSCode user, you can install the


associated extension: axe Accessibility Linter.

➥ Tip # 77. Refactor React code e ortlessly with


react-codemod

Codemods are transformations that run on your


codebase programmatically . 💻
They make it easy to refactor your codebase.

For example, React codemods can help you remove all


React imports from your codebase, update your code to
use the latest React features, and more.

So, make sure to check those out before manually


refactoring your code.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 115 / 140

➥ Tip # 78. Transform your app into a


Progressive Web Application (PWA) using vite-
pwa

Progressive Web Applications (PWAs) load like regular


web pages but offer functionality such as working
offline, push notifications, and device hardware access.

You can easily create a PWA in React using vite-pwa.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 116 / 140

CATEGORY #11: REACT & VISUAL


STUDIO CODE 🛠
➥ Tip # 79. Enhance your productivity with the
Simple React Snippets snippets extension

Bootstrapping a new React component can be tedious


😩 .

Snippets from the Simple React Snippets extension


make it easier.

➥ Tip # 80. Set


editor.stickyScroll.enabled to true
to quickly locate the current component

I love this feature ❤.


If you have a big file, it can be hard to locate the current
component.

By setting editor.stickyScroll.enabled to
true , the current component will always be at the top
of the screen.

❌ Without sticky scroll


💡 Without Sticky Scroll
✅ With sticky scroll
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 117 / 140

💡 With Sticky Scroll

➥ Tip # 81. Simplify refactoring with extensions


like VSCode Glean or VSCode React Refactor

If you need to refactor your code frequently (for example,


extract JSX into a new component), make sure to check
out extensions like VSCode Glean or VSCode React
Refactor.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 118 / 140

CATEGORY #12: REACT &


TYPESCRIPT 🚀
➥ Tip # 82. Use ReactNode instead of
JSX.Element | null | undefined |
... to keep your code more compact

I see this mistake a lot.

Instead of typing the leftElement and


rightElement props like this:

const Panel = ({ leftElement, rightElement


}: {
leftElement:
| JSX.Element
| null
| undefined
// | ...;
rightElement:
| JSX.Element
| null
| undefined
// | ...
}) => {
// …
};

You can use ReactNode to keep the code more


compact.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 119 / 140

const MyComponent = ({
leftElement,
rightElement,
}: {
leftElement: ReactNode,
rightElement: ReactNode,
}) => {
// …
};

➥ Tip # 83. Simplify the typing of components


expecting children props with
PropsWithChildren

You don't have to type the children prop manually.

In fact, you can use PropsWithChildren to simplify


the typings.

// 🟠 Ok
const HeaderPage = ({
children,
...pageProps
}: { children: ReactNode } & PageProps) =>
{
// …
};

// ✅Better
const HeaderPage = ({

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 120 / 140

children,
...pageProps
}: PropsWithChildren<PageProps>) => {
// …
};

➥ Tip # 84. Access element props e ciently


with ComponentProps ,
ComponentPropsWithoutRef ,…

There are cases where you need to figure out a


component's props.

For example, let's say you want a button that will log to
the console when clicked.

You can use ComponentProps to access the props of


the button element then override the click prop.

const ButtonWithLogging = (props:


ComponentProps<"button">) => {
const handleClick:
MouseEventHandler<HTMLButtonElement> = (e)
=> {
console.log("Button clicked"); //TODO:
Better logging
props.onClick?.(e);
};
return <button {...props} onClick=
{handleClick} />;
};
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 121 / 140

This trick also works with custom components.

const MyComponent = (props: { name: string


}) => {
// …
};

const MyComponentWithLogging = (props:


ComponentProps<typeof MyComponent>) => {
// …
};

➥ Tip # 85. Leverage types like


MouseEventHandler , FocusEventHandler
and others for concise typings

Rather than typing the event handlers manually, you can


use types like MouseEventHandler to keep the code
more concise and readable.

// 🟠 Ok
const MyComponent = ({
onClick,
onFocus,
onChange,
}: {
onClick: (e:

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 122 / 140

MouseEvent<HTMLButtonElement>) => void,


onFocus: (e:
FocusEvent<HTMLButtonElement>) => void,
onChange: (e:
ChangeEvent<HTMLInputElement>) => void,
}) => {
// …
};

// ✅ Better
const MyComponent = ({
onClick,
onFocus,
onChange,
}: {
onClick:
MouseEventHandler<HTMLButtonElement>,
onFocus:
FocusEventHandler<HTMLButtonElement>,
onChange:
ChangeEventHandler<HTMLInputElement>,
}) => {
// …
};

➥ Tip # 86. Specify types explicitly in useState,


useRef, etc., when the type can't be or shouldn't
be inferred from the initial value

Don't forget to specify the type when it can't be inferred


from the initial value.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 123 / 140

For example, in the example below, there is a


selectedItemId stored in the state. It should be a
string or undefined .

since the type is not specified, TypeScript will infer the


type as undefined , which is not what we want.

// ❌Bad: `selectedItemId` will be


inferred as `undefined`
const [selectedItemId, setSelectedItemId] =
useState(undefined);

// ✅ Good
const [selectedItemId, setSelectedItemId] =
(useState < string) | (undefined >
undefined);

💡 Note: The opposite of this is that you don't need


to specify the type when TypeScript can infer it for
you.

➥ Tip # 87. Leverage the Record type for


cleaner and more extensible code

I love this helper type.

Let's say I have a type that represents log levels.

type LogLevel = "info" | "warn" | "error";

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 124 / 140

We have a corresponding function for each log level that


logs the message.

const logFunctions = {
info: (message: string) =>
console.info(message),
warn: (message: string) =>
console.warn(message),
error: (message: string) =>
console.error(message),
};

Instead of typing the logFunctions manually, you can


use the Record type.

const logFunctions: Record<LogLevel,


(message: string) => void> = {
info: (message) => console.info(message),
warn: (message) => console.warn(message),
error: (message) =>
console.error(message),
};

Using the Record type makes the code more concise


and readable.

Additionally, it helps capture any error if a new log level


is added or removed.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 125 / 140

For example, if I decided to add a debug log level,


TypeScript would throw an error.

➥ Tip # 88. Use the as const trick to


accurately type your hook return values

Let's say we have a hook useIsHovered to detect


whether a div element is hovered.

The hook returns a ref to use with the div element and
a boolean indicating whether the div is hovered.

const useIsHovered = () => {


const ref = useRef < HTMLDivElement >
null;
const [isHovered, setIsHovered] =
useState(false);
// TODO : Rest of implementation
return [ref, isHovered];
};

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 126 / 140

Currently, TypeScript will not correctly infer the function


return type.

You can either fix this by explicitly typing the return type


like this:

const useIsHovered = ():


[RefObject<HTMLDivElement>, boolean] => {
// TODO : Rest of implementation
return [ref, isHovered];
};

Or you can use the as const trick to accurately type


the return values:

const useIsHovered = () => {


// TODO : Rest of implementation
return [ref, isHovered] as const;
};

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 127 / 140

➥ Tip # 89. Redux: Ensure proper typing by


referring to https://react-redux.js.org/using-
react-redux/usage-with-typescript to correctly
type your Redux state and helpers

I love using Redux to manage heavy client-side state.

It also works well with TypeScript.

You can find a great guide on how to use Redux with


TypeScript here.

➥ Tip # 90. Simplify your types with


ComponentType

Let's say you're designing an app like Figma (I know,


you're ambitious ). 😅
The app is made of widgets, each accepting a size .

To reuse logic, we can define a shared WidgetWrapper


component that takes a widget of type Widget defined
as follows:

interface Size {
width: number;
height: number;
}

interface Widget {
title: string;

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 128 / 140

Component: ComponentType<{ size: Size }>;


}

The WidgetWrapper component will render the widget


and pass the relevant size to it.

const WidgetWrapper = ({ widget }: {


widget: Widget }) => {
const { Component, title } = widget;
const { onClose, size, onResize } =
useGetProps(); //TODO: better name but you
get the idea 😅
return (
<Wrapper onClose={onClose} onResize=
{onResize}>
<Title>{title}</Title>
{/* We can render the component below
with the size */}
<Component size={size} />
</Wrapper>
);
};

➥ Tip # 91. Make your code more reusable with


TypeScript generics

If you're not using TypeScript generics, only two things


could be happening:

You are either writing very simple code or,


Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 129 / 140

You are missing out 😅


TypeScript generics make your code more reusable and
flexible.

For example, let's say I have different items on a blog


(e.g., Post , Follower , etc.), and I want a generic list
component to display them.

export interface Post {


id: string;
title: string;
contents: string;
publicationDate: Date;
}

export interface User {


username: string;
}

export interface Follower extends User {


followingDate: Date;
}

Each list should be sortable.

There is a bad and a good way to do this.

❌ Bad: I create a single list component that accepts a


union of items.

This is bad because:

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 130 / 140

Every time a new item is added, the


functions/types must be updated.
The function is not entirely type-safe (see This
shouldn't happen comment).
This code depends on other files (e.g.:
FollowerItem , PostItem ).
Etc.

import { FollowerItem } from


"./FollowerItem";
import { PostItem } from "./PostItem";
import { Follower, Post } from "./types";

type ListItem =
| { type: "follower", follower: Follower
}
| { type: "post", post: Post };

function ListBad({
items,
title,
vertical = true,
ascending = true,
}: {
title: string,
items: ListItem[],
vertical?: boolean,
ascending?: boolean,
}) {
const sortedItems = [...items].sort((a,
b) => {
const sign = ascending ? 1 : -1;
return sign * compareItems(a, b);
});

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 131 / 140

return (
<div>
<h3 className="title">{title}</h3>
<div className={`list ${vertical ?
"vertical" : ""}`}>
{sortedItems.map((item) => (
<div key={getItemKey(item)}>
{renderItem(item)}</div>
))}
</div>
</div>
);
}

function compareItems(a: ListItem, b:


ListItem) {
if (a.type === "follower" && b.type ===
"follower") {
return (
a.follower.followingDate.getTime() -
b.follower.followingDate.getTime()
);
} else if (a.type == "post" && b.type ===
"post") {
return a.post.publicationDate.getTime()
- b.post.publicationDate.getTime();
} else {
// This shouldn't happen
return 0;
}
}

function getItemKey(item: ListItem) {


switch (item.type) {
case "follower":
return item.follower.username;
case "post":

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 132 / 140

return item.post.id;
}
}

function renderItem(item: ListItem) {


switch (item.type) {
case "follower":
return <FollowerItem follower=
{item.follower} />;
case "post":
return <PostItem post={item.post} />;
}
}

Instead, we can use TypeScript generics to create a


more reusable and type-safe list component.

I made an example in the sandbox below 👇.


🏖 https://codesandbox.io/p/devbox/generics-ts-
zvfp6n?file=%2Fsrc%2Fcomponents%2FList.tsx

➥ Tip # 92. Ensure precise typing with the


NoInfer utility type

Imagine you're developing a video game 🎮.


The game has multiple locations (e.g., LeynTir ,
Forin , Karin , etc.).

You want to create a function that teleports the player to


a new location.
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 133 / 140

function teleportPlayer<L extends string>(


position: Position,
locations: L[],
defaultLocation: L
): L {
// Teleport the player and return the
location
}

The function will be called this way:

const position = { x: 1, y: 2, z: 3 };
teleportPlayer(position, ["LeynTir",
"Forin", "Karin"], "Forin");
teleportPlayer(position, ["LeynTir",
"Karin"], "anythingCanGoHere"); // This ❌
will work, but it is wrong since
"anythingCanGoHere" shouldn't be a valid
location

The second example is invalid because


anythingCanGoHere is not a valid location.

However, TypeScript will not throw an error since it


inferred the type of L from the list and the default
location.

To fix this, use the NoInfer utility type.

function teleportPlayer<L extends string>(


position: Position,
Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 134 / 140

locations: L[],
defaultLocation: NoInfer<L>
): NoInfer<L> {
// Teleport the player and return the
location
}

Now TypeScript will throw an error:

teleportPlayer(position, ["LeynTir",
"Karin"], "anythingCanGoHere"); // ❌
Error: Argument of type
'"anythingCanGoHere"' is not assignable to
parameter of type '"LeynTir" | "Karin"

Using the NoInfer utility type ensures that the default


location must be one of the valid locations provided in
the list, preventing invalid inputs.

➥ Tip # 93. E ortlessly type refs with the


ElementRef type helper

There is a hard and easy way to type refs.

The hard way is to remember the element's type name


and use it directly . 🤣
const ref = useRef<HTMLDivElement>(null);

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 135 / 140

The easy way is to use the ElementRef type helper.


This method is more straightforward since you should
already know the element's name.

const ref = useRef<ElementRef<"div">>


(null);

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 136 / 140

CATEGORY #13: MISCELLANEOUS


TIPS 🎉
➥ Tip # 94. Boost your code's quality and safety
with eslint-plugin-react and Prettier.

You can't be serious about React if you're not using


eslint-plugin-react . 😅
It helps you catch potential bugs and enforce best
practices.

So, make sure to install and configure it for your project.

You can also use Prettier to format your code


automatically and ensure your codebase is consistent.

➥ Tip # 95. Log and monitor your app with tools


like Sentry or Grafana Cloud Frontend
Observability.

You can't improve what you don't measure 📏.


If you're looking for a monitoring tool for your production
apps, check out Sentry or Grafana Cloud Frontend
Observability.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 137 / 140

➥ Tip # 96. Start coding quickly with online IDEs


like Code Sandbox or Stackblitz

Local development environments can be a pain to set


up.

Especially as a beginner 🐣.
So start with online IDEs like Code Sandbox or
Stackblitz.

These tools allow you to start coding quickly without


worrying about setting up your environment.

➥ Tip # 97. Looking for advanced react skills?


Check out these books 👇
If you're looking for advanced React books 📚 , I would
recommend:

Advanced React by @adevnadia


Fluent React by @TejasKumar_
Building Large Scale Web Apps by @addyosmani
and @djirdehh

➥ Tip # 98. Prepping React interviews? Check


reactjs-interview-questions

React interviews ⚛ can be tricky.


Made with ❤ by Ndeye Fatou Diop
101 React Tips & Tricks 138 / 140

Luckily, you can prep for them by checking this repo.

➥ Tip # 99. Learn React best practices from


experts like Nadia, Dan, Josh, Kent, etc.

If you want to stay up-to-date with the best practices


and learn tips, make sure to follow experts like:

@adevnadia: https://x.com/adevnadia for


advanced react tips
@joshwcomeau: https://x.com/joshwcomeau
@kentcdodds: https://x.com/kentcdodds
@mattpocockuk: https://x.com/mattpocockuk for
TypeScript tips
@TejasKumar*: https://x.com/TejasKumar*
@housecor: https://x.com/housecor
or me 😅
: https://x.com/_ndeyefatoudiop

➥ Tip # 100. Stay updated with the React


ecosystem by subscribing to newsletters like This
Week In React or ui.dev

React is a fast-moving ecosystem.

There are many tools, libraries, and best practices to


keep up with.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 139 / 140

To stay updated, make sure to subscribe to newsletters


💌 like:

This Week In React by @sebastienlorber


ui.dev
Etc.

➥ Tip # 101. Engage with the React community


on platforms like r/reactjs

The React community is fantastic.

You can learn a lot from other developers and share your
knowledge.

So engage with the community on platforms like


r/reactjs.

Made with ❤ by Ndeye Fatou Diop


101 React Tips & Tricks 140 / 140

CONCLUSION

I hope this book has helped you learn some new React
tips and tricks . 🚀
I look forward to seeing what you build with React - feel
free to let me know how it's going on X/Twitter. You can
reach me at @_ndeyefatoudiop.

If you would like more tips/tricks, make sure to


subscribe to my newsletter, FrontendJoy.

A NOTE ON SHARING

If you'd like to share this book, I kindly ask that you


direct them to this link:
https://ndeyefatoudiop.gumroad.com/l/101-react-tips-
and-tricks.

This provides valuable analytics about how many people


are reading the book, and gives me a way to reach out to
readers directly.

This book is and always will be free to download ✨

Made with ❤ by Ndeye Fatou Diop

You might also like