为什么 RTK 查询响应处理不起作用?
Why does RTK query response handling not work?
我尝试在登录请求中使用 RTK 查询,但在打印结果时遇到了一些问题。这是我的代码。
authRTK.ts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { loginForm, UserResponse } from "../type/type";
import { RootState } from "./store";
export const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:3001',
prepareHeaders: (headers, { getState }) => {
// By default, if we have a token in the store, let's use that for authenticated requests
const token = (getState() as RootState).auth.token;
if (token) {
headers.set("authentication", `Bearer ${token}`);
}
return headers;
}
}),
endpoints: (build) => ({
login: build.mutation<UserResponse, loginForm>({
query: (credentials) => ({
url: "login",
method: "POST",
body: credentials
}),
transformResponse: (response: { data: UserResponse }) => {
return response.data
},
}),
protected: build.mutation({
query: () => "protected"
})
})
});
export const { useLoginMutation,useProtectedMutation } = api;
store.ts
import { configureStore } from '@reduxjs/toolkit'
import cartReducer from './cartRedux';
import userReducer from './authRedux';
import { api } from './authRTK';
export const store = configureStore({
reducer:{
cart: cartReducer,
auth: userReducer,
[api.reducerPath]: api.reducer,
},
middleware: (gDM) => gDM().concat(api.middleware),//getDefaultMiddleware
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
Login.tsx
const Login = () => {
const [login, { isLoading,error,isError}] = useLoginMutation();
const [showPassword,setShowPassword] = useState<boolean>(false);
return (
<Container>
<Wrapper>
{/* <button onClick={()=>testCookie()}>測試一下cookie</button> */}
<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){
console.log(result.data)
}else{
console.log((result.error as RequestError).data) ////this will printout the expected result , but I have to cast error to RequestError type to print the nested data inside , and I can't use this data else where like error above
console.log(error) //This printout undefined,mean there's no error data inside,but not supposed to happen
console.log(isError) //print out false , but supposed to be true
}
}catch(err){
console.log(err)
}
}}>
{({
errors,
values,
handleChange,
handleBlur,
handleSubmit,
validateField
}) => (
<Form onSubmit={handleSubmit}>
<InputContainer>
<Input
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
type="text"
name="email"
placeholder="Email"
data-testid="email"
/>
</InputContainer>
{errors.email && <Error data-testid="emailError">{errors.email}</Error>}
<InputContainer>
<Input
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
type={showPassword ? "text" : "password"}
name="password"
placeholder="Password"
data-testid="password"
/>
{showPassword ? <VisibilityOff onClick={()=>setShowPassword(false) }/> : <Visibility onClick={()=>setShowPassword(true) }/> }
</InputContainer>
{errors.password && <Error data-testid="passwordError">{errors.password}</Error>}
<Button
data-testid="submit"
type="submit">Submit</Button>
</Form>
)}
</Formik>
</Wrapper>
</Container>
);
};
export default Login;
所以我的主要问题是 login.tsx,错误没有按预期工作,我的响应数据必须确定其中是否有“数据”,即使我使用了 transformResponse。
顺便说一句,我的回复类型如下所示
请求错误:
{
data:string;
status:string
}
data
不是您回复中的 data
。即触发函数结果的data
属性
trigger
始终 returns { data: ... }
或 { error: ... }
.
形式的对象
所以如果没有你的 transformResult,你最终会得到 result.data.data
而不是 result.data
。
你也可以打开它,直接获取数据并在错误情况下抛出错误,但这不是默认设置,因为如果你不处理它可能会导致未捕获的承诺拒绝错误。
async (values, actions) => {
try{
const result = await login(values).unwrap();
console.log(result.data)
} catch(err){
console.log(err)
}
}
我尝试在登录请求中使用 RTK 查询,但在打印结果时遇到了一些问题。这是我的代码。
authRTK.ts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { loginForm, UserResponse } from "../type/type";
import { RootState } from "./store";
export const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:3001',
prepareHeaders: (headers, { getState }) => {
// By default, if we have a token in the store, let's use that for authenticated requests
const token = (getState() as RootState).auth.token;
if (token) {
headers.set("authentication", `Bearer ${token}`);
}
return headers;
}
}),
endpoints: (build) => ({
login: build.mutation<UserResponse, loginForm>({
query: (credentials) => ({
url: "login",
method: "POST",
body: credentials
}),
transformResponse: (response: { data: UserResponse }) => {
return response.data
},
}),
protected: build.mutation({
query: () => "protected"
})
})
});
export const { useLoginMutation,useProtectedMutation } = api;
store.ts
import { configureStore } from '@reduxjs/toolkit'
import cartReducer from './cartRedux';
import userReducer from './authRedux';
import { api } from './authRTK';
export const store = configureStore({
reducer:{
cart: cartReducer,
auth: userReducer,
[api.reducerPath]: api.reducer,
},
middleware: (gDM) => gDM().concat(api.middleware),//getDefaultMiddleware
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
Login.tsx
const Login = () => {
const [login, { isLoading,error,isError}] = useLoginMutation();
const [showPassword,setShowPassword] = useState<boolean>(false);
return (
<Container>
<Wrapper>
{/* <button onClick={()=>testCookie()}>測試一下cookie</button> */}
<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){
console.log(result.data)
}else{
console.log((result.error as RequestError).data) ////this will printout the expected result , but I have to cast error to RequestError type to print the nested data inside , and I can't use this data else where like error above
console.log(error) //This printout undefined,mean there's no error data inside,but not supposed to happen
console.log(isError) //print out false , but supposed to be true
}
}catch(err){
console.log(err)
}
}}>
{({
errors,
values,
handleChange,
handleBlur,
handleSubmit,
validateField
}) => (
<Form onSubmit={handleSubmit}>
<InputContainer>
<Input
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
type="text"
name="email"
placeholder="Email"
data-testid="email"
/>
</InputContainer>
{errors.email && <Error data-testid="emailError">{errors.email}</Error>}
<InputContainer>
<Input
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
type={showPassword ? "text" : "password"}
name="password"
placeholder="Password"
data-testid="password"
/>
{showPassword ? <VisibilityOff onClick={()=>setShowPassword(false) }/> : <Visibility onClick={()=>setShowPassword(true) }/> }
</InputContainer>
{errors.password && <Error data-testid="passwordError">{errors.password}</Error>}
<Button
data-testid="submit"
type="submit">Submit</Button>
</Form>
)}
</Formik>
</Wrapper>
</Container>
);
};
export default Login;
所以我的主要问题是 login.tsx,错误没有按预期工作,我的响应数据必须确定其中是否有“数据”,即使我使用了 transformResponse。
顺便说一句,我的回复类型如下所示
请求错误:
{
data:string;
status:string
}
data
不是您回复中的 data
。即触发函数结果的data
属性
trigger
始终 returns { data: ... }
或 { error: ... }
.
所以如果没有你的 transformResult,你最终会得到 result.data.data
而不是 result.data
。
你也可以打开它,直接获取数据并在错误情况下抛出错误,但这不是默认设置,因为如果你不处理它可能会导致未捕获的承诺拒绝错误。
async (values, actions) => {
try{
const result = await login(values).unwrap();
console.log(result.data)
} catch(err){
console.log(err)
}
}