Common React Pitfalls

Photo by Lautaro Andreani on Unsplash
This is a document which tries to collect common Pitfalls that developers fall into when learning React for the first time.
Can’t call <method> on <undefined>
This is usually caused by misunderstanding the component lifecycle. Components in React render synchronously, which means that the first time a component renders it will often have no data, or empty data.
Example:
import { useState, useEffect } from "react";
import { getPosts } from "api";
function App() {
const [posts, setPosts] = useState();
useEffect(() => {
getPosts.then((posts) => setPosts(posts));
}, []);
return (
<div className="posts">
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</div>
);
}
In this example the first time this component loads, because we passed nothing
into useState the state will be undefined, Then in the JSX, we call
posts.map which is trying to call the map function on an undefined value.
Since useEffect is asynchronous, it does not call the getPosts method on
initial render. Instead React will call useEffect after render. Once we
have gotten the list of posts, we then call setPosts which updates the state
of the component and triggers a re-render of the component.
Solution 1: A better default state
One solution to this problem is to make sure we have some initial state we can
call .map on, so by making the initial state an empty array, we accomplish
that goal:
const [posts, setPosts] = useState([]);
Solution 2: Conditional Rendering
Conditional rendering is often the best solution to this problem. Basically guard against empty data in the function by checking to see if you have the data.
if (!posts) {
return <p>There are no posts</p>;
}