使用Redux Toolkit时响应数据无法写入entities数组如何排查?
问题原因&修复方案
1. 异步Thunk无返回值,导致payload为undefined
你当前在createAsyncThunk的回调函数中混合使用了await和.then写法,且没有将接口返回值向外返回,最终fulfilled回调中拿到的payload为undefined,自然无法写入state。
同时你代码中打印的response.data.data.json()是错误写法:如果是axios封装的api,响应已经自动解析为JS对象,不需要调用.json()方法(该方法属于fetch API),执行会直接报错。
修正后Thunk代码:
export const LoginAuthentication = createAsyncThunk( 'user/login', async ({inp_email, inp_password}, {rejectWithValue}) => { try { const response = await api.post('/auth/login',{ email: inp_email, password: inp_password, session: '1' }) // 可以在这里打印确认返回结构 console.log(response.data.data) return response.data.data } catch (error) { return rejectWithValue(error.response.data?.message) } } )
2. EntityAdapter方法使用错误
createEntityAdapter的setAll方法要求传入实体对象数组来替换整个集合,而登录接口返回的是单个用户对象,应该使用setOne方法写入单条数据。
同时注意:setOne要求实体对象必须包含id字段作为唯一标识,如果你的返回用户信息里唯一键不是id,需要在创建适配器的时候指定id字段:
// 比如你的用户唯一键是user_id,就这么写 const LoginAdapter = createEntityAdapter({ selectId: (user) => user.user_id })
修正后extraReducers代码:
extraReducers: (builder) => { builder .addCase(LoginAuthentication.pending, (state) => { state.isLoading = true }) .addCase(LoginAuthentication.fulfilled, (state, {payload}) => { state.isLoading = false // 单条数据用setOne LoginAdapter.setOne(state, payload) }) .addCase(LoginAuthentication.rejected, (state) => { state.isLoading = false }) }
注:Redux Toolkit官方更推荐使用builder链式写法定义extraReducers,对TS支持更好也不会出现对象键名的潜在问题。
3. 选择器定义错误
你当前定义的selectUser取值逻辑错误,entityAdapter生成的state结构为{ ids: [], entities: {}, isLoading: false },没有login字段,可以直接用适配器生成的内置选择器取数据:
// 生成内置选择器 export const { selectAll: selectAllUsers, selectById: selectUserById } = LoginAdapter.getSelectors( (state) => state.user ) // 因为登录只有一个用户,也可以直接定义取第一个用户的选择器 export const selectCurrentUser = (state) => selectAllUsers(state)?.[0]
内容的提问来源于stack exchange,提问作者DevGe
相关产品推荐
相关产品推荐

