I’m doing simple react blog app which renders simple posts list from https://jsonplaceholder.typicode.com/posts:
//...
function App() {
const [posts, setPosts] = useState<IPost[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts`)
.then((response) => {
if (!response.ok) {
throw new Error(
`This is an HTTP error: The status is ${response.status}`
);
}
return response.json();
})
.then((posts) => {
setPosts(posts.filter((p: IPost) => p.id < 3));
setError(null);
})
.catch((err) => {
setError(err.message);
setPosts([]);
})
.finally(() => {
setLoading(false);
});
}, []);
return (
<div className="App">
<PostsList posts={posts} />
</div>
);
}
export default App;
export interface IPost {
id: number;
title: string;
}
function PostsList({ posts }: { posts: Array<IPost> }) {
const postData = posts === null ? [] : posts;
const renderedPosts = postData.map((post) => <Post post={post} />);
console.log("Render...");
return <div className="flex flex-col">{renderedPosts}</div>;
}
function Post({ post }: { post: IPost }) {
return (
<div key={post.id} className="post my-4 p-6">
<h2 className="text-2xl mb-4">{post.title}</h2>
</div>
);
}
It renders fine. But in console I see:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `PostsList`. See https://reactjs.org/link/warning-keys for more information.
...
And It renders PostsList
several times. All post ids are unique… So, I can figure out why I get this warning. Does anybody tell me what am I doing wrong?
I expect render without warnings.
2
Answers
The
key
is part of the list rendering process, not the component itself. Move thekey
to themap
callback:And remove it from the component:
In your
PostsList
component, you are usingpostData.map()
to loop through the posts and render each post as a Post component. However, you are not providing a unique key prop for each Post component.React uses the
key
prop to identify each element. If it updates etc.You need to add a
key
prop to yourPost
component :