typescript Reactjs重新渲染组件并显示“警告:列表中的每个子元素都应该有一个唯一的“键”属性,

hivapdat  于 2023-05-08  发布在  TypeScript
关注(0)|答案(2)|浏览(150)

我正在做一个简单的react博客应用程序,它可以从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>
  );
}

它呈现良好。但在控制台我看到:

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.
...

它渲染了PostsList几次。所有帖子ID都是唯一的。。所以,我可以弄清楚为什么我得到这个警告。有没有人告诉我我做错了什么?
我希望在没有警告的情况下进行渲染。

wvyml7n5

wvyml7n51#

key是列表呈现过程的一部分,而不是组件本身。将key移动到map回调:

const renderedPosts = postData.map((post) => <Post key={post.id} post={post} />);

并将其从组件中删除:

function Post({ post }: { post: IPost }) {
  return (
    <div className="post my-4 p-6">
      <h2 className="text-2xl mb-4">{post.title}</h2>
    </div>
  );
}
piok6c0g

piok6c0g2#

在您的PostsList组件中,您使用postData.map()循环遍历帖子并将每个帖子呈现为Post组件。但是,您并没有为每个post组件提供唯一的键属性。
React使用key prop来标识每个元素。如果更新等等。
您需要将key属性添加到post组件:

function PostsList({ posts }: { posts: Array<IPost> }) {
  const postData = posts === null ? [] : posts;
  const renderedPosts = postData.map((post) => <Post key={post.id} post={post} />);
  console.log("Render...");
  return <div className="flex flex-col">{renderedPosts}</div>;
}

相关问题