What this article series are about 🔍
This article series are basically a summary of You Might Not Need an Effect, which is a React official documentation about the usage of useEffect
hook in React.
The original article is really really good, for sure better than my summary. So, if you have time, I highly recommend you to read the original article.
My motivation is just to provide a quick summary both for myself and for others who might be busy or a bit lazy to read through the whole article.
Yeah, it's for you 😉 haha
I summarized the content as short as possible, so we can get main idea quickly.
So don't forget to check the original article for more detailed information. Again, it's really good learning material.
When something can be calculated from the existing props or state, we don't need extra state and useEffect
Bad 👎
function Form() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
// 🔴 Unnecessary extra state and useEffect
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);
//
return (
<div>
<input
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
placeholder="First Name"
/>
<input
value={lastName}
onChange={(e) => setLastName(e.target.value)}
placeholder="Last Name"
/>
<h1>{fullName}</h1>
</div>
);
}
Good 👍
function Form() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
// ✅ No extra state and useEffect
const fullName = firstName + ' ' + lastName;
return (
<div>
<input
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
placeholder="First Name"
/>
<input
value={lastName}
onChange={(e) => setLastName(e.target.value)}
placeholder="Last Name"
/>
<h1>fullName</h1>
</div>
);
}
Takeaway
The point is to let re-render do the calculation, instead of doing it with extra state and useEffect
.
When we call setFirstName or setLastName, we trigger a re-render, and then the next fullName will be calculated from the fresh data.
Reference
When we use useEffect
just to update something only when some props or state is updated, what we really need is useMemo
.
Bad 👎
getFilteredTodos
is a function that filters todos based on the filter, and it is used to calculate visibleTodos
.
Maybe you want to update visibleTodos
only when todos
or filter
changes.
function TodoList({ todos, filter }) {
const [newTodo, setNewTodo] = useState('');
// 🔴 Unnecessary extra state and useEffect
const [visibleTodos, setVisibleTodos] = useState([]);
useEffect(() => {
setVisibleTodos(getFilteredTodos(todos, filter));
}, [todos, filter]);
...
}
Good 👍
function TodoList({ todos, filter }) {
const [newTodo, setNewTodo] = useState('');
// ✅ No extra state and useEffect, but efficient use of useMemo
const visibleTodos = useMemo(
() => getFilteredTodos(todos, filter),
[todos, filter]
);
}
Takeaway
If your motivation to use useEffect
is just to update something only when some props or state is updated, what you really need is useMemo
.
Reference
When we want to reset the state based on some prop change, we could do it witout useEffect
Bad 👎
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selectedItem, setSelectedItem] = useState(null);
// 🔴 Avoid: resetting state on prop change in an Effect
useEffect(() => {
setSelection(null);
}, [items]);
// ...
}
Good 👍
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
// Change selectedItem to selectedItemId, so that we don't need to reset state on prop change
const [selectedItemId, setSelectedItemId] = useState(null);
// ✅ No extra state and useEffect, just calculate selectedItem when selectedItemId changes
const selectedItem = useMemo(items.find((item) => item.id === selectedItemId);,[items, selectedItemId]);
}
Takeaway
When you adjusting or resetting the state based on some prop change, you better to think about the way to do it without useEffect
Top comments (0)