You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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标签,不会触发单个帖子查询的重新获取

修复步骤:

  1. 给getPostById添加单个帖子的标签声明:
getPostById: builder.query<Post, number>({
  query: (id) => `/posts/${id}`,
  // 为单个帖子提供专属标签
  providesTags: (result, error, id) => [{ type: "Posts", id }]
}),
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:20:43