RTK Query配置问题:未登录无法访问公开帖子接口求助
问题描述
我开发了一个简易应用,需求是允许公众查看所有帖子,但用户需认证后才能创建和删除自己的帖子。按当前方式配置后出现错误:TypeError: Cannot read properties of null (reading 'token') buildThunks.ts:448,未登录状态下无法获取帖子。我刚接触RTK Query,请问是否可以配置为允许未认证用户仅调用getPosts和getPost接口?
相关代码
RTK Query 配置
export const postApi = createApi({ reducerPath: "postApi", baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3001", prepareHeaders: (headers, { getState }) => { const token = ( (getState()).auth.user.token ) if(token){ headers.set('authorization', `Bearer ${token}`) return headers } }, }), tagTypes: ["Post"], endpoints: (builder) => ({ getPosts: builder.query({ query: ()=> ({ url: "/api/posts", method: 'GET' }), providesTags: ["Post"] }), getPost: builder.query({ query: (id) => ({ url: `/api/posts/:${id}`, method: 'GET' }), providesTags: ['Post'] }), createPost: builder.mutation({ query: (formData) => ({ url: "/api/posts", method: 'POST', body: formData }), invalidatesTags: ["Post"] }), deletePost: builder.mutation({ query: (id) => ({ url: `/api/posts/${id}`, method: 'DELETE', body: id }), invalidatesTags: ["Post"] }) }) }) export const { useGetPostsQuery, useGetPostQuery, useCreatePostMutation, useDeletePostMutation } = postApi
后端路由配置
import express from 'express' import { deletePost, getPost, getPosts, newPost } from '../controllers/Post.js' import { auth } from '../middleware/auth.js' const router = express.Router() //get posts router.get('/', getPosts) //get post router.get('/:id', getPost) //create post router.post('/', auth, newPost) //delete post router.delete('/:id', auth, deletePost) export default router
解决方案
当然可以,问题核心是prepareHeaders的空值处理逻辑错误,以及getPost接口的URL路径写法有误,以下是修复步骤:
1. 修复prepareHeaders的空值报错
未登录时auth.user为null,直接读取token会触发报错,同时必须确保无论是否有token都返回headers(之前的代码仅在有token时返回,无token时会返回undefined导致请求异常):
prepareHeaders: (headers, { getState }) => { const authState = (getState()).auth; // 逐层判断避免空值访问 if (authState?.user?.token) { headers.set('authorization', `Bearer ${authState.user.token}`); } // 始终返回headers return headers; },
2. 修正getPost的URL路径错误
原代码中/api/posts/:${id}会生成错误路径(比如/api/posts/:123),应该改为/api/posts/${id}才能匹配后端路由。
3. 可选:给特定接口单独配置无认证请求
如果后端对未认证GET请求不接受Authorization头,可以给getPosts和getPost单独设置不带prepareHeaders的baseQuery:
getPosts: builder.query({ query: ()=> ({ url: "/api/posts", method: 'GET' }), baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3001" }), providesTags: ["Post"] }), getPost: builder.query({ query: (id) => ({ url: `/api/posts/${id}`, method: 'GET' }), baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3001" }), providesTags: ['Post'] }),
最终完整RTK Query代码
export const postApi = createApi({ reducerPath: "postApi", baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:3001",", prepareHeaders: (headers, { getState }) => { const authState = (getState()).auth; if (authState?.user?.token) { headers.set('authorization', `Bearer ${authState.user.token}`); } return headers; }, }), tagTypes: ["Post"], endpoints: (builder) => ({ getPosts: builder.query({ query: ()=> ({ url: "/api/posts", method: 'GET' }), providesTags: ["Post"] }), getPost: builder.query({ query: (id) => ({ url: `/api/posts/${id}`, method: 'GET' }), providesTags: ['Post'] }), createPost: builder.mutation({ query: (formData) => ({ url: "/api/posts", method: 'POST', body: formData }), invalidatesTags: ["Post"] }), deletePost: builder.mutation({ query: (id) => ({ url: `/api/posts/${id}`, method: 'DELETE', body: id }), invalidatesTags: ["Post"] }) }) }) export const { useGetPostsQuery, useGetPostQuery, useCreatePostMutation, useDeletePostMutation } = postApi
内容的提问来源于stack exchange,提问作者JackieWebDev
相关产品推荐
相关产品推荐

