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

如何在useEffect中调用RTK Query获取登录用户的购物车数据

问题根因

报错的核心原因是违反了React的Hook调用规则:所有Hook必须在组件的顶层作用域调用,不能嵌套在useEffect、条件判断、普通函数内部。useGetCartByIDQuery本身是RTK Query生成的自定义Hook,放在useEffect的条件分支里自然无法正常运行。同时你原有useEffect的依赖写的是dispatch,dispatch是稳定引用永远不会变化,会导致这个effect只会在组件首次挂载时执行一次,监听不到登录后的用户数据更新。


解决方案

方案1(推荐):使用skip参数控制请求(符合RTK Query设计规范)

直接把Query移到组件顶层,通过skip参数控制是否发起请求,不需要手动写useEffect触发:

const Login = () => {
  const user = useAppSelector(state=> state.auth);
  const dispatch = useAppDispatch();
  const [login] = useLoginMutation();
  const [showPassword,setShowPassword] = useState<boolean>(false);
  // Query移到组件顶层,用skip控制请求时机
  const {data: cartData, isLoading: cartLoading, isFetching: cartFetching }= useGetCartByIDQuery(user?.user?._id!, {
    // 用户不存在/没有用户ID时跳过请求
    skip: !user?.user?._id
  })

  // 如果需要把购物车数据存入你的UserCartData slice,加这个effect同步即可
  useEffect(() => {
    if(cartData){
      dispatch(setCartData(cartData)) // 替换为你自己的购物车slice更新方法
    }
  }, [cartData, dispatch])

  return (
    <Container>
      <Wrapper>
        <Title>SIGN IN</Title>
        <Formik
          initialValues={{ email: "", password: "" }}
          validationSchema={Yup.object({
            password: Yup.string()
              .min(8, 'Must be 8 characters or higher')
              .required(),
            email: Yup.string().email('Invalid email address').required(),
          })}
          onSubmit = {  async (values, actions) => {
                try{
                  const result = await login(values);
                  if("data" in result){
                    dispatch(setCredentials({user:result.data.data.findUser,token:result.data.data.cookie}))
                    
                  }else{
                    const err = (result.error as RequestError).data.message
                    if(err.includes("password")){
                      actions.setErrors({password:err})
                    }else if(err.includes("Facebook")){
                      actions.setErrors({email:err})
                    }
                  }
                }catch(err){
                  console.log(err)
                }             
          }}>
          {/* 其余原有代码 */}

RTK Query会自动在skip变为false的时候发起请求,同时内置缓存、加载状态管理,不需要额外维护购物车相关状态。


方案2:使用懒加载Query手动触发

如果你需要完全手动控制请求触发时机,可以用RTK Query自动生成的lazy版本Query:

const Login = () => {
  const user = useAppSelector(state=> state.auth);
  const dispatch = useAppDispatch();
  const [login] = useLoginMutation();
  const [showPassword,setShowPassword] = useState<boolean>(false);
  // 用懒加载Query拿到触发函数
  const [triggerGetCart, {data: cartData, isLoading: cartLoading}] = useLazyGetCartByIDQuery();

  // 监听user变化,存在时手动触发请求
  useEffect(() => {
    if (user?.user?._id){ 
      triggerGetCart(user.user._id)
    }
  }, [user, triggerGetCart])

  // 同步购物车数据到slice的逻辑和方案1一致
  useEffect(() => {
    if(cartData){
      dispatch(setCartData(cartData))
    }
  }, [cartData, dispatch])

  // 其余原有代码不变

内容的提问来源于stack exchange,提问作者Kai021195

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 07:09:00