RTK Query更新数据后页面未自动刷新,MUI Rating组件无法禁用
问题:评分更新后页面未自动刷新,Rating组件未禁用
我用MUI的Rating组件实现帖子评分功能,点击评分后后端数据已经更新,但页面没刷新,导致Rating组件没按照“加载后评分非零则禁用”的逻辑变成禁用状态。以下是帖子组件及API切片的代码,请问为何更新后未自动重新获取数据?
帖子组件代码
import { Button, Rating } from "@mui/material"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import { useGetPostByIdQuery, useUpdatePostByIdMutation, } from "../../features/api/apiSlice"; type Post = { id: number; title: string; body: string; userId: number; date: string; rating: number; }; export function SinglePost() { const { postId } = useParams(); const [value, setValue] = useState<number | null>(); const { data: post, isLoading, isSuccess, isError, refetch, } = useGetPostByIdQuery(Number(postId)); const [updatePost] = useUpdatePostByIdMutation(); let title; let body; let rating; if (isSuccess) { title = ( <h1 style={{ color: "white", textAlign: "center" }}>{post.title}</h1> ); body = <p style={{ color: "white", textAlign: "center" }}>{post.body}</p>; rating = ( <Rating key={Math.random()} name="size-large" size="large" value={post.rating} onChange={(event, newValue) => { updatePost({ id: Number(postId), title: post.title, body: post.body, userId: post.userId, date: post.date, rating: Number(newValue), }); }} disabled={post.rating !== 0 ? true : false} /> ); } else if (isError) { title = <h1 style={{ color: "white" }}>Title Error!</h1>; body = <p>Body Error!</p>; } return ( <div style={{ height: "500px", backgroundColor: "rgb(10, 25, 41)", width: "500px", display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", }} > {title} <br /> {body} <br /> {rating} </div> ); }
API切片代码
import { createEntityAdapter, createSelector, EntityState, } from "@reduxjs/toolkit"; import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; type Post = { id: number; title: string; body: string; userId: number; date: string; rating: number; }; export const apiSlice = createApi({ reducerPath: "api", baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3000" }), tagTypes: ["Posts", "Users"], endpoints: (builder) => ({ getPosts: builder.query<Post[], void>({ query: () => "/posts", transformResponse: (res: Post[]) => res.sort((a, b) => b.id - a.id), providesTags: (result) => result ? [ ...result.map(({ id }) => ({ type: "Posts" as const, id })), { type: "Posts", id: "LIST" }, ] : [{ type: "Posts", id: "LIST" }], }), getUsers: builder.query<User[], void>({ query: () => "/users", providesTags: ["Users"], }), getPostById: builder.query<Post, number>({ query: (id) => `/posts/${id}`, }), getUserById: builder.query<User, number>({ query: (id) => `/users/${id}`, }), updatePostById: builder.mutation<Post, Partial<Post>>({ query: (post: Post) => { const { id, ...body } = post; return { url: `posts/${id}`, method: "PUT", body, }; }, invalidatesTags: [{ type: "Posts", id: "LIST" }], }), }), }); export const { useGetPostsQuery, useGetUsersQuery, useGetPostByIdQuery, useGetUserByIdQuery, useUpdatePostByIdMutation, } = apiSlice;
解答
问题根源在RTK Query的标签管理机制:
getPostById接口没有配置providesTags,无法标记单个帖子的缓存标签updatePostById的invalidatesTags只失效了帖子列表的LIST标签,不会触发单个帖子查询的重新获取
修复步骤:
- 给
getPostById添加单个帖子的标签声明:
getPostById: builder.query<Post, number>({ query: (id) => `/posts/${id}`, // 为单个帖子提供专属标签 providesTags: (result, error, id) => [{ type: "Posts", id }] }),
- 修改
updatePostById的失效标签,同时覆盖单个帖子和列表:
updatePostById: builder.mutation<Post, Partial<Post>>({ query: (post: Post) => { const { id, ...body } = post; return { url: `posts/${id}`, method: "PUT", body, }; }, invalidatesTags: (result, error, arg) => [ // 失效当前更新的单个帖子标签 { type: "Posts", id: arg.id }, // 同时失效列表标签(如果需要列表同步更新) { type: "Posts", id: "LIST" } ] }),
额外优化建议:
- 删掉
Rating组件上的key={Math.random()},这会导致组件不必要的频繁重渲染 disabled属性可以简化为disabled={post.rating !== 0},无需三元表达式
内容的提问来源于stack exchange,提问作者ether
相关产品推荐
相关产品推荐

