为什么RTK Query的响应与错误处理未按预期工作?
问题原因分析
- RTK Query的mutation触发函数返回的Promise默认不会抛错,始终返回一个包含
data或error字段的对象,所以必须做字段判断才能拿到对应值,这是RTK Query的默认设计。你用到的transformResponse仅用来处理成功请求的返回值,不会修改mutation返回的包裹结构,所以不会省略掉data字段的判断步骤。 - 你在Formik的
onSubmit回调里直接读取hook返回的error和isError会碰到闭包陷阱:回调里存储的是组件初始渲染时的变量快照,请求完成后的最新状态还没触发组件重渲染,所以你拿到的永远是初始的undefined和false。 - 你定义mutation的时候没有指定错误泛型,所以TS默认不知道你的错误结构是
RequestError,才需要手动强转类型。
解决步骤
1. 给mutation指定错误泛型,避免强转
修改authRTK.ts里的login mutation定义,传入第三个泛型参数指定错误类型:
login: build.mutation<UserResponse, loginForm, { data: RequestError }>({ query: (credentials) => ({ url: "login", method: "POST", body: credentials }), transformResponse: (response: { data: UserResponse }) => { return response.data }, }),
2. 使用unwrap()直接获取响应数据/抛出错误
如果你不想每次都判断data字段,可以在调用login之后加.unwrap(),这样请求成功会直接返回data值,请求失败会抛出错误,你可以直接在catch里捕获错误:
onSubmit = { async (values, actions) => { try{ const result = await login(values).unwrap(); // 这里直接拿成功数据,不用判断data字段 console.log(result) }catch(err){ // 这里直接拿到错误,类型已经是RequestError console.log(err.data) } }}
3. 如果你要使用hook返回的error、isError状态
不要在onSubmit回调里读取这些值,这些值需要在组件渲染的顶层读取,直接渲染到UI上:
const Login = () => { const [login, { isLoading, error, isError}] = useLoginMutation(); const [showPassword,setShowPassword] = useState<boolean>(false); return ( <Container> <Wrapper> <Title>SIGN IN</Title> {/* 直接在UI层使用错误状态 */} {isError && <Error>{(error as RequestError).data}</Error>} {/* 其余Formik代码保持不变 */} </Wrapper> </Container> ) }
内容的提问来源于stack exchange,提问作者Kai021195
相关产品推荐
相关产品推荐

