React Tips
React Tips
Bogdan Adrian
1
26. Always check for booleans in JSX.
27. Do not use inline CSS.
28. Don’t use inline functions if possible.
29. Avoid stale closures.
30. Use children props to stop re-rendering the
children components.
31. Fetching in useEffect does not fit the React
mental model.
32. Understand identities when working with lists.
33. Lift the custom hook up.
34. Semantic HTML in React.
35. Don't build blind branches in JSX.
36. Put functions outside the component.
37. Do not put the theme (light/ dark) in any global
state (Context, Redux etc).
38. Don't use Context as global state manager.
39. Make use of the useReducer hook more often.
40. Don’t put JSX in custom hooks.
41. Don’t pass entire objects as props if possible.
42. Don’t import SVGs as JSX or directly in React.
43. Always, no matter what, do only one thing in
useEffect.
44. Why useEffect needs functions too in its
dependency array.
45. Don’t plug in data in weird ways.
46. Don’t try to control renders on React.
47. Don’t use ternary in JSX if possible.
48. What for and when to use the useCallback hook.
49. Don’t use setInterval in useEffect.
50. Whenever you have JSX repeating itself, extract
the logic to a config object and loop through it.
51. Destructure Props on Component call.
52. Avoid Nested Ternary Operators.
53. Use composition instead of Context.
54. Do not send the all application bundle to the
client.
55. Error handling is as important as all the other
React code.
2
56. Remove all the Listeners When Unmounting
Components.
57. Toggle CSS instead of forcing a component to
mount and unmount.
58. How and why to Use Dependency Injection in React.
59. Use virtualization for large lists.
60. Learn to work with complex data from parent to
child.
61. Understand why you lose all the state when you
refresh the browser.
62. Use the useRef hook to access properties on DOM
elements.
63. Don’t use “create-react-app” for your production
app.
64. Refactor old jQuery apps to React.
65. Use the linter to avoid syntax bugs.
66. Pay careful attention to the function's identity.
67. Why and when to use useMemo.
68. Clean up the useEffect after async operations -
use an helper variable if needed.
69. What is a HOC and why you might need it
(sometimes).
70. What is Render Props and why you might need it.
71. What is the flow data Flux and why does it matter
in React.
72. Learn the difference between reactive and not
reactive state to write better React code.
73. Use enums to conditionally return form functions
or even components.
74. What global state manager to use.
75. Learn what shallow compared values are and why
they matter a lot in React.
3
1. Always ask for help.
4
Sometimes bad teammates exist of course,
but that should not be your problem.
Usually, they are being known and
observed in the teams.
5
2. JavaScript to know for React.
6
For example, it is not enough you know
Array.map(); you need to know all the
Array methods.
7
3. How and where to learn React
from.
But why?
8
Because there is so much going on under
the hood and those few apis may be used
in so many different ways that you can
learn all of this only by experience and
not by learning.
9
- What are props and the pitfalls of
them like prop drilling and identity
of props.
- Conditional rendering;
- JavaScript in JSX;
- Handling events
- Creating forms and understanding their
local state pattern.
10
Many other topics that I do not remember
now but you’ll encounter along your
preparation for becoming a React dev
journey. Problems included.
11
4. How to think of components?
12
By verbose I mean not necessarily too big
but with too many conditions to display.
13
5. Take care of your naming.
14
“Correct naming eliminates the need for
comments”.
15
Avoid names like email(), product() etc.
These names sound like properties. Prefer
getProduct() etc., instead.
16
You may want to add a hook (we will see
in another Tip), for dealing with the
logic for getting the user position.
Name it `useUserPosition`.
17
6. Use UUID (or similar), on the
data source and not at the
component level!
18
Whenever the component renders the id
will be different because the re-render
will call the UUID function again and
that confuses React.
Instead of this:
{React.Children.toArray(someData.map(item
=> <div>{item.title}</div>)}
19
7. Use shorthand for boolean
props.
<Component isAllowed={true}
showToast={true} />
20
8. Write a fragment when a div is
not needed.
🔴
const Component = () => {
// Will throw an error
return (
<h1>Welcome!</h1>
<p>We are a hosting provider</p>
)
}
21
<p>We are a hosting provider</p>
</>
)
}
22
9. Before going deep into React
advanced concepts, make sure you
know CSS and HTML well enough.
Why?
23
In whatever job you’ll get, there will
never be someone else to write CSS for
the code that is charged on you.
24
10. Don’t pass unrecognised props
to JSX elements.
25
example: “isUserLoggedIn” prop coming
from destructuring restProps for example.
26
11. Don’t enclose string props in
curly braces.
27
12. Write self closing components
when there are no children to
pass.
28
13. Create a folder for each
component and export an index.tsx
from it.
29
If the component needs to be split into
subcomponents, create a “components”
folder inside the component folder and
put each subcomponent in it.
If there is a translation for it, add the
folder with languages to it.
30
14. Restrict styling with themes.
Why?
31
To provide better predictability to your
component’s behaviour (including its
visual appearance) limit the degree of
freedom your component consumers have in
overriding your component styling
properties.
32
15. Understand the differences
between React.memo and useMemo.
33
But if that calculation depends on a prop
for example, which changes on each
re-render, using useMemo is a pain rather
than a help. So pay careful attention.
34
16. Make wise use of the key prop.
35
React assigns a “key” prop to every
single element in the application.
36
17. Learn to always keep your data
objects immutated.
37
const users = [
{name: user.name },
{name user.name}
...
]
const newUsers =
[...users.map(...transform data here) ]
38
Please notice: keeping reactive data
immutated in React is a pattern that will
heavily impact your render cycle.
39
18. Don’t abuse the useEffect
hook.
40
However, we developers tend to use it for
much more.
41
Do that in the component and not in
useEffect.
Why?
42
Props are some sort of data that belongs
to React already.
43
19. Avoid setting a new state
whenever possible.
44
You can use the component render itself
to derive data.
45
Many times the useState can and should be
replaced with useRef.
46
In refs you can store whatever value you
want, besides referencing DOM elements.
47
to store values that need to be shown in
JSX.
48
20. Learn to recognize the reasons
a component re-renders.
- Parent renders,
- New props is received,
- State is set,
- New Context value arrives.
49
Sometimes you can’t stop a parent from
re-rendering a lot for different reasons.
Maybe it shows in the UI some often
changing state for example.
50
In that case, take a look at the props it
receives.
51
How to debug too many renders.
52
When the answer from async comes, the
loop may stop.
53
21. Decompose your tree
strategically.
54
A component can be as big as you want in
terms of JSX and there is nothing wrong
with that.
55
22. Avoid overusing 3rd party
libraries for trivial things.
56
23. Imports/Exports pattern.
Also:
57
Prefer named exports over default.
58
24. Import order matters.
2. Platform/framework-level imports,
starting with the most important ones,
core technology, like react for Web
app, react then react-native for
Native App or express for Server App.
59
ones that have more "impact" on the
app. If there are packages of the same
importance, then they should be just
ordered alphabetically.
4. Non-platform-specific libraries
(like d3) and smaller libraries that
extend those libraries (like
d3-path-interpolate for d3). Ordered
alphabetically but grouped around some
"main libs” (like all the d3-related
imports would be grouped together
instead of being scattered amongst
other imports).
60
Note: There should be a blank line
between package imports (e.g., import {
... } from 'some-package') and relative
imports (e.g., import { ... } from
'../../somewhere/in/our/code') and no
other blank lines between imports.
import {
Button,
61
Content,
dimensions,
Page,
Paper,
Typography,
ScrollView,
useTheme,
} from '@company/package-ui-kit-native';
62
import { ... } from 'lodash';
import { ... } from 'yup';
import { ... } from
'@bitwala/package-theme';
import { ... } from
'@company/package-ui-kit-native';
63
25. React components and specific
hooks for each.
Why?
Bad!
64
the way they are implemented internally
is pretty much universal.
Component-specific hooks.
65
Component-specific hook is named strictly
after the component (using the
use<COMPONENT_NAME> convention) and is
collocated within the component folder.
66
really specific to the original component
it was created for.
67
component (anything except purely UI
things), there might be hooks like:
68
have anything else, consider only having
the useMyComponentAnimations hook for it
and handle everything else (e.g., if it
needs a couple formatted translation
strings besides the animations) in the
component itself.
69
26. Always check for booleans in
JSX.
Or:
Don't do only
70
Is it an array and you need to check if
it exists?
Is it an object?
71
!!obj.name && ...
Object.entries(obj).length > 0 && ...
Is it a function?
72
27. Do not use inline CSS.
73
Creating new objects in JavaScript has
its cost.
<input
className={isAllowed ? 'input_allowed' :
'input_not_allowed'
... />
74
28. Don’t use inline functions if
possible.
75
Therefore if you like using inline
functions please feel free to do so.
76
not new and will spare a function from
being created.
77
<Button onClick={() => setState(value)}>
Click
</Button>
78
29. Avoid stale closures.
79
Stale closures may happen in many
situations but the most frequent ones are
when data that changes are missing from a
dependency array in useEffect,
useCallback or useMemo.
80
And so do useEffect, useCallback or
useMemo.
81
const inner = outerFunction(1);
inner(1) // 2
inner(1) // 2
inner(1) // 2
82
in, whenever the values in its dependency
array change.
83
the same handler if the state is the new
value you set.
84
30. Use children props to stop
re-rendering the children
components.
85
Passing children components with children
props is an underrated powerful React
pattern.
86
I know this is a pretty harsh pattern to
wrap your head around, but once you do
that you will have much more control on
your React render cycle.
87
31. Fetching in useEffect does not
fit the React mental model.
88
The response decides for you.
89
32. Understand identities when
working with lists.
90
When an aeroplane lands, what do you do?
91
The boolean may be toggled to switch it
between “true” and “false” in a
handleToggle function.
92
33. Lift the custom hook up.
93
value of that custom hook statement, it
would not work unless you lift the hook
up to the nearest parent that both
components are plugged in!
94
34. Semantic HTML in React.
95
Whatever app that stands behind
authentication!
96
35. Don't build blind branches in
JSX.
97
36. Put functions outside the
component.
98
In the case when you create functions
inside the component, the function will
be recreated new on every render of the
component.
99
37. Do not put the theme (light/
dark) in any global state
(Context, Redux etc).
100
With CSS variables you avoid those
re-renders all together and the UI is
more consistent!
101
38. Don't use Context as global
state manager.
102
No. They have some similarities and
overlap, but there are major differences
in their capabilities.
103
Use Context only for dependency
injection.
104
39. Make use of the useReducer
hook more often.
React docs:
105
logic that involves multiple sub-values
or when the next state depends on the
previous one. useReducer also lets you
optimise performance for components that
trigger deep updates because you can pass
dispatch down instead of callbacks.
106
Too many useState in the same component
may introduce hard to catch bugs in your
app. It all depends when and how those
setState are called. Instead, useReducer
dispatch function is predictable and has
no such a pitfall.
107
40. Don’t put JSX in custom hooks.
108
41. Don’t pass entire objects as
props if possible.
109
42. Don’t import SVGs as JSX or
directly in React.
110
I will link you to an article which
explains why this is not good and what to
do:
https://benadam.me/thoughts/react-svg-spr
ites
111
happens because of a request waterfall.
First the Browser downloads the HTML
document. It then makes the subsequent
requests to fetch all the assets for the
page (images, scripts, stylesheets, etc).
The benefit of referencing an external
asset is caching. The browser (or CDN)
can cache the asset and reference it on
subsequent requests. The technique is
optimised for subsequent requests, but
the initial loading experience is less
than desirable. The other downside of
this technique is that we can't style the
😢
svg using CSS when it is referenced in an
image tag .”.
112
43. Always, no matter what, do
only one thing in useEffect.
113
“Dispatch” does not change its identity
as it is stable, but think of any other
example when a function changes its
identity etc.
114
44. Why useEffect needs functions
too in its dependency array.
115
The functions need to go into the array
dependency simply because it is used in
the useEffect callback and because of
that useEffect needs to run whenever the
“dispatch” identity changes.
116
In that case, the handler identity will
overwrite the returned value however and
determine useEffect to re-run.
117
45. Don’t plug in data in weird
ways.
118
in a reactish way and not using your
hacks!
React docs:
119
46. Don’t try to control renders
on React.
React is declarative.
120
Can you imagine a river?
Be like a river!
121
47. Don’t use ternary in JSX if
possible.
122
React does not unmount it for mounting
the other one. It just “renders the same
tag”, (may be a component with the same
name) with a different placeholder prop.
123
48. What for and when to use the
useCallback hook.
Here's why:
124
When you are using functions inside a
component, those functions do their job
whenever they are invoked. Next, they get
garbage collected if nobody references
them anymore!
125
useCallback memoaizes that function. This
means it does not let it die (by a
closure that references it so it hangs
around in memory).
126
49. Don’t use setInterval in
useEffect.
127
new compared to the previous setInterval
(which probably didn’t get to the end
yet).
128
50. Whenever you have JSX
repeating itself, extract the
logic to a config object and loop
through it.
129
Don’t create JSX for every variant!
130
But if you like an array better, feel
free to use an array.
131
51. Destructure Props on component
call.
132
A specific type of function which can
take whatever arguments (called props),
and which always returns JSX markup.
133
52. Avoid Nested Ternary
Operators.
134
53. Use composition instead of
Context.
135
Basically we return a component from a
parent which takes a children prop or
other component (or components) or which
can take props as other subchildren
components.
136
- Avoiding props drilling. If you have a
state in the App, you can pass it to
the Children3 directly from the App.
In practice you can pass “data” down
several components without any prop
drilling and without using any state
manager.
- Using the native bail-out React
mechanism and limiting the number of
re-renders. In the case of Children2
and Children3 no React.createElement
is called in the App so no new props
are passed down to them, even when
there is no prop at all! So, no
re-render!
137
themselves first then into the superior
level tree, you can do everything you may
want with the global local state.
React Docs:
138
React Composition is a development
pattern based on React's original
component model where we build components
from other components using explicit
defined props or the implicit children
prop.
In terms of refactoring, React
composition is a pattern that can be used
to break a complex component down to
smaller components, and then composing
those smaller components to structure and
complete your application.
139
54. Do not send the all
application bundle to the client.
140
In React we have the Lazy loading
technique which we can use to split the
bundle size sent to the client.
We can split the application at the route
level!
https://reactjs.org/docs/code-splitting.h
tml
141
55. Error handling is as important
as all the other React code.
142
consistent and follow the same pattern
everywhere in your app.
- catch errors;
- handle the UI accordingly;
- log the errors.
143
It is a custom class component that is
used as a wrapper of the entire
application.
144
The big drawback of this approach is that
it doesn't handle errors in asynchronous
callbacks, on server-side-rendering, or
in event-handlers because they're outside
the boundary.
https://github.com/JoschuaSchneider/use-e
rror-boundary
145
56. Remove all the Listeners When
Unmounting Components.
146
For example, listen for onScroll to
dynamically perform some action when the
user scrolls the page.
Why?
147
57. Toggle CSS instead of forcing
a component to mount and unmount.
148
Rendering is costly, especially when the
change must be committed to the real DOM.
149
Toggling the opacity to 0 has almost zero
cost for the browser (since it doesn’t
cause a reflow) and should be preferred
over visibility & display changes
whenever possible.
150
58. How and why to Use Dependency
Injection in React.
151
What is dependency injection?
152
When you switch the language, you need
the entire app to update with the newly
set language.
153
in the entire app or locally to some
tree.
154
Do you know how the Providers pattern
works in React?
155
59. Use virtualization for large
lists.
156
The slowdown may be noticed very quickly
and the app becomes unresponsive,
especially on slow devices.
157
60. Learn to work with complex
data from parent to child.
158
One of the most confusing patterns in
React but also the most useful is passing
complex data from parent to Children in
order to compose new data and use it for
API calls.
159
Only the new data you’ll send will be a
newly created array of specialised
“products” and will contain some
properties from the data you fetched
combined with some new user-created data
properties which will be added to that
new element.
160
Then, whenever the user clicks on ‘Add to
cart’, let's say, I need to save a new
object to a new state with the id of that
product and the addToCart property set to
true.
161
61. Understand why you lose all
the state when you refresh the
browser.
React is a SPA.
Single Page Application.
162
The outside store is directly tied to a
browser instance.
163
feeding again that empty store with new
data just arrived.
164
62. Use the useRef hook to access
properties on DOM elements.
165
But that is a bit more cumbersome to do.
There is also a:
containerRef.current?.scrollTo(x-ccord,
y-coord)
containerRef.current?.scrollTo(0) is
going to take the user to the top of the
page.
166
63. Don’t use “create-react-app”
for your production app.
Why?
But,
167
Dependencies are primarily plain
JavaScript that does not often change
during development. Some significant
dependencies (ex MaterialUi) are also
quite expensive to process.
168
64. Refactor old jQuery apps to
React.
<script
src="https://unpkg.com/react@18/umd/react
.production.min.js" crossorigin></script>
<script
src="https://unpkg.com/react-dom@18/umd/r
eact-dom.production.min.js"
crossorigin></script>
<script
src="https://unpkg.com/@babel/standalone/
babel.min.js"></script>
<script src="like-button.js"
type="text/babel"></script>
169
Add capability to add JSX:
- npm init -y
- npm install babel-cli@6
babel-preset-react-app@3
170
65. Use the linter to avoid syntax
bugs.
171
66. Pay careful attention to the
function's identity.
172
For example, in the snippet of code above
you need to set the language with the
Context.
173
67. Why and when to use useMemo.
174
68. Clean up the useEffect after
async operations - use an helper
variable if needed.
Why?
175
state you want to set with the response
will try to fire.
176
What if the async operation you perform
in useEffect has no method to be
cancelled?
177
69. What is a HOC and why you
might need it (sometimes).
178
Meanwhile hooks apply very well the
separation of concerns principles, are
tied to a component instance and they are
much more readable on the human side
thean HOCs.
179
HOCs are React components which take
other components as arguments and return
those components with some functionality
added.
In JavaScript:
180
Let’s say you have a custom hook which
reacts to some state change.
181
the Component, and could enhance any
component passed as argument.
182
Recap: A HOC is a component container
which can take other components as
arguments and add functionality to them.
183
70. What is Render Props and why
you might need it.
184
The function can be called from the props
or from the children props.
185
71. What is the unidirectional
flow data Flux and why does it
matter in React.
React is declarative.
186
And the data we feed React with is
divided in snapshots (or frames), like it
was a picture of all the data and how it
looks at every given moment in time.
187
We usually watch a movie from beginning
to the end.
188
parents, making sure that a clean data
flow architecture is followed.
189
72. Learn the difference between
reactive and not reactive state to
write better React code.
190
execution, and values that can change
during execution.
- Api responses,
- State from useState,
- Values from refs,
- User actions,
- Hard coded variables.
191
snapshot of data into the UI, moment
after moment.
192
However, if you are using React Query for
example or any sync with the server
mechanism, an api response might change
quite often therefore I can affirm that
an api response is reactive data too.
193
73. Use enums to conditionally
return from functions or even
components.
So checkUserCondition is going to be
Requested. It also can be a component if
194
you want too. Just return a component
from the enums instead of a string.
195
196
74. What global state manager to
use?
- Redux,
- Redux Toolkit (RTK),
- Recoil,
- Zustand,
- Valtio,
- Jotai,
- Mobx
197
There are also particular tools which
can’t be put in the category of global
state manager because they can only do
one thing.
198
75. Learn what shallow compared
values are and why they matter a
lot in React.
199
oldProps.onClick !== newProps.onClick,
your component will keep “seeing” the
props and state from a previous render
inside its onClick handler, leading to
very confusing bugs.
200
But what does a component that re-renders
close over old props from parent means?
201