我项目的Inbox Api如下:

const baseQuery = fetchBaseQuery({
  baseUrl: "http://localhost:8000",
});

export const apiSlice = createApi({
  baseQuery,
  tagTypes: ["User"],
  endpoints: (builder) => ({}),
});

我使用apiSlice.injectEndpoints()注入updateUser端点. 更新用户端点如下:

updateUser: builder.mutation({
      query: ({ data, token }) => ({
        url: `${USERS_URL}/profile`,
        method: "PUT",
        body: data,
        headers: { Authorization: `Bearer ${token}` },
      }),
    }),

现在,在后台,当用户注册或登录时,我会生成一个令牌.当用户(例如登录)时,响应由用户凭证和令牌组成.登录代码为:

const authUser = asyncHandler(async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findOne({ email });
  if (user && (await user.matchPassword(password))) { // matchPw is a method in user model
    const token = generateToken(user._id);
    res.status(201).json({
      _id: user._id,
      name: user.name,
      email: user.email,
      token,
    });
  } else {}});

登录成功后,该操作将通过登录响应进行调度,该响应保存在Inbox存储中为:

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    setCredentials: (state, action) => {
      state.userInfo = action.payload;
      AsyncStorage.setItem("userInfo", JSON.stringify(action.payload))
        .then(() => console.log("User successfully saved"))
        .catch((err) => console.error("Error saving user: ", err));
      console.log(state.userInfo)
    },
    logout: (state) => {
      state.userInfo = null
      AsyncStorage.removeItem("userInfo")
      console.log(state)
    }
  },
});

现在,在我的reactnative组件(updateuserProfile.jsx)中,我获得userInfo为:

const userInfo = useSelector((state) => state.auth.userInfo);
const token = userInfo.token;
console.log(token)

这将成功注销登录期间创建的令牌.

现在,当updateuserProfile.jsx中的字段被编辑并提交以进行更新时:

const handleSubmit = async () => {
    if (password != confirmPassword) {
      alert("Passwords donot match");
    } else {
      try {
        console.log("Frontend token: ", token);
        const res = await updateUser({
          data: {
            _id: userInfo._id,
            name,
            email,
            password,
          },
          token,
        }).unwrap();
        dispatch(setCredentials({ ...res })); // update the credentials as well
        alert("Profile updated");
      } catch (err) {
        alert(err?.data?.message || err.error);
      }
    }
  };

这里,行console.log("Frontend token: ", token);也成功注销令牌.

现在将击中的端点是/api/users/profile .此路由是受保护的路由,因为它需要用户经过身份验证,即用户必须拥有令牌才能更新其个人资料.要保护的路由代码如下:

import jwt from "jsonwebtoken";
import asyncHandler from "express-async-handler";
import User from "../models/userModel.js";

const protect = asyncHandler(async (req, res, next) => {
  let token = req.headers.authorization;
  console.log("token: ", token);

  if (token && token.startsWith("Bearer ")) {
    token = token.split(" ")[1];
    //if there is a token, we need to verify it
    try {
      //decode the token
      const decoded = jwt.verify(token, process.env.JWT_SECRET); //decoded is a object, that now has a userId field
      req.user = await User.findById(decoded.userId).select("-password"); //find the user with the id in the decoded object, as we don't want to return the password we do -password
      // doing req.user allows us to access the current user in the protected routes by simply using req.user
      next();
    } catch (error) {
      res.status(401);
      throw new Error("Not authorized, invalid token!");
    }
  } else {
    res.status(401);
    throw new Error("Not authorized, no token!");
  }
});

export { protect };

在第console.log("token: ", token);行中,我收到的日志(log)是token: Bearer undefined,即我传递headers: { Authorization: `Bearer ${token}` }的查询,已检测到"Bearer",但"token"保持未定义.

推荐答案

Query函数仅接受单个arg.

export type query = <QueryArg>(
  arg: QueryArg,
) => string | Record<string, unknown>

更新您的updateUser端点以使用具有进行查询所需属性的单个arg对象.

updateUser: builder.mutation({
  query: ({ data, token }) => ({
    url: `${USERS_URL}/profile`,
    method: "PUT",
    body: data,
    headers: { Authorization: `Bearer ${token}` },
  }),
}),

更新已调度的触发器函数以传递单个参数.请务必实际解包装已解析的查询结果.

try {
  const res = await updateUser({
    data: {
      _id: userInfo._id,
      name,
      email,
      password,
    },
    token
  }).unwrap();
  dispatch(setCredentials({ ...res }));
} catch(error) {
  // handle/ignore errors
}

React-native相关问答推荐

将 Cognito 用户与真实数据库用户联系起来的最佳方式是什么?

如何在react-native 中存储/保存数据

React Native Android:how to remove "overscroll effect" of ScrollView

如何在StackNavigator 中实现自定义标题图标?

如何在 Crashlytics (Fabrics) 中有效地对非致命异常进行分组?

使用 Hooks 在功能组件中react-navigation 标题

纯在 Swift 中的 React Native 应用程序

更改默认的 React Native 下拉箭头图标

如何使用 Stripe (stripe.js) 和 react-native

try 在 Android 上运行我的 React Native 应用程序时出错

iOS 模拟器如何确认alert信息

React Native 无法运行堆栈跟踪

react-native 中的倒数计时器

React Native Navigation 组件路由问题

您将如何在 Alert 中模拟onPress?

如何在react-native中关闭模态

更改导航标题背景 colored颜色

运行 expo start 时如何禁用在浏览器中打开 DevTools?

React Native,更改 React Navigation 标题样式

React Navigation 切换背景 colored颜色 和样式 StackNavigator