每当我在更改映射组件后重新获取反应查询时,下一个组件的更改状态显示为 "success"
Whenever i refetch in react query after mutating a mapped component, the status of the mutation of the next component shows as "success"
我正在从我的 express 后端获取并显示一个 post 数组,它显示为“博客”组件。
list of posts
该组件有一个按钮可以从后端删除它,然后重新获取 posts,每当我点击删除按钮时,状态从“空闲”变为“加载”再变为“成功”并且然后在重新获取数据时将其删除。
这行得通,但是当它被删除时,下一个 post 显示“成功”作为状态。为什么?
post "title 2" is deleted and post 3 displays status as "success"
BlogPost.jsx:
import React from "react";
import axios from "axios";
import { useQueryCache, useMutation } from "react-query";
const deleteBlog = ({ postID }) => {
return axios.delete(`/api/posts/${postID}`, { withCredentials: true });
};
const BlogPost = ({ postID, title, content }) => {
const [mutation, { status }] = useMutation(deleteBlog);
const queryCache = useQueryCache();
return (
<div style={{ border: "medium solid red", padding: 5 }}>
{`status: ${status}`}
<button
onClick={() => {
mutation({ postID }).then(() => {
queryCache.invalidateQueries("posts");
});
}}
>
delete
</button>
<h2>{title}</h2>
<h3>{postID}</h3>
<p>{content}</p>
</div>
);
};
export default BlogPost;
Landing.jsx:
import React from "react";
import BlogPost from "../components/BlogPost";
import axios from "axios";
import { useQuery } from "react-query";
const posts = () => {
return axios.get("/api/posts").then((resp) => resp.data);
};
const Landing = () => {
const { data, isSuccess, refetch } = useQuery("posts", posts);
return (
<div>
<button
onClick={() =>
axios
.post(
"/api/posts",
{ title: "title", content: "content" },
{ withCredentials: true }
)
.then(() => refetch())
}
>
New post
</button>
{isSuccess &&
data.map((post, index) => {
return (
<BlogPost
key={index}
postID={post._id}
title={post.title}
createdDate={post.createdAt}
author={post.author}
content={post.content}
/>
);
})}
</div>
);
};
export default Landing;
快递后端:
let fakedb = [
{
_id: "0",
title: "title",
createdAt: "1234",
author: "Lorem",
content: "453",
},
];
app.get("/api/posts", (req, res) => {
res.json(fakedb);
});
app.post("/api/posts", (req, res) => {
const { title, content } = req.body;
fakedb.push({
title,
_id: fakedb.length.toString(),
content,
createdAt: "456",
author: "1",
});
res.sendStatus(200);
});
app.delete("/api/posts/:postID", (req, res) => {
fakedb = fakedb.filter((i) => i._id !== req.params.postID);
res.sendStatus(200);
});
有两个要点可以理解正在发生的事情:
status
是变异请求的状态
Landing.jsx
使用索引作为 BlogPost
组件的键。
键是 React 唯一用来识别 DOM 元素的东西。在删除操作后重新获取数据时,现在响应数据是一个包含 3 个博客 post 对象的数组。因为您使用索引作为键,React 认为数组中的第 3 个元素(在索引 3 之前但现在是索引 2)与之前的元素相同。由于道具不同,它 re-render 组件。此时组件保持着之前操作的状态。
React documentation警告不要使用键,因为它会显示错误的数据。
查看 Robin Pokorny’s article 以获得关于使用索引作为键的负面影响的 in-depth 解释。
我正在从我的 express 后端获取并显示一个 post 数组,它显示为“博客”组件。
list of posts
该组件有一个按钮可以从后端删除它,然后重新获取 posts,每当我点击删除按钮时,状态从“空闲”变为“加载”再变为“成功”并且然后在重新获取数据时将其删除。
这行得通,但是当它被删除时,下一个 post 显示“成功”作为状态。为什么?
post "title 2" is deleted and post 3 displays status as "success"
BlogPost.jsx:
import React from "react";
import axios from "axios";
import { useQueryCache, useMutation } from "react-query";
const deleteBlog = ({ postID }) => {
return axios.delete(`/api/posts/${postID}`, { withCredentials: true });
};
const BlogPost = ({ postID, title, content }) => {
const [mutation, { status }] = useMutation(deleteBlog);
const queryCache = useQueryCache();
return (
<div style={{ border: "medium solid red", padding: 5 }}>
{`status: ${status}`}
<button
onClick={() => {
mutation({ postID }).then(() => {
queryCache.invalidateQueries("posts");
});
}}
>
delete
</button>
<h2>{title}</h2>
<h3>{postID}</h3>
<p>{content}</p>
</div>
);
};
export default BlogPost;
Landing.jsx:
import React from "react";
import BlogPost from "../components/BlogPost";
import axios from "axios";
import { useQuery } from "react-query";
const posts = () => {
return axios.get("/api/posts").then((resp) => resp.data);
};
const Landing = () => {
const { data, isSuccess, refetch } = useQuery("posts", posts);
return (
<div>
<button
onClick={() =>
axios
.post(
"/api/posts",
{ title: "title", content: "content" },
{ withCredentials: true }
)
.then(() => refetch())
}
>
New post
</button>
{isSuccess &&
data.map((post, index) => {
return (
<BlogPost
key={index}
postID={post._id}
title={post.title}
createdDate={post.createdAt}
author={post.author}
content={post.content}
/>
);
})}
</div>
);
};
export default Landing;
快递后端:
let fakedb = [
{
_id: "0",
title: "title",
createdAt: "1234",
author: "Lorem",
content: "453",
},
];
app.get("/api/posts", (req, res) => {
res.json(fakedb);
});
app.post("/api/posts", (req, res) => {
const { title, content } = req.body;
fakedb.push({
title,
_id: fakedb.length.toString(),
content,
createdAt: "456",
author: "1",
});
res.sendStatus(200);
});
app.delete("/api/posts/:postID", (req, res) => {
fakedb = fakedb.filter((i) => i._id !== req.params.postID);
res.sendStatus(200);
});
有两个要点可以理解正在发生的事情:
status
是变异请求的状态Landing.jsx
使用索引作为BlogPost
组件的键。
键是 React 唯一用来识别 DOM 元素的东西。在删除操作后重新获取数据时,现在响应数据是一个包含 3 个博客 post 对象的数组。因为您使用索引作为键,React 认为数组中的第 3 个元素(在索引 3 之前但现在是索引 2)与之前的元素相同。由于道具不同,它 re-render 组件。此时组件保持着之前操作的状态。
React documentation警告不要使用键,因为它会显示错误的数据。
查看 Robin Pokorny’s article 以获得关于使用索引作为键的负面影响的 in-depth 解释。