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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:00:34