使用 createAsyncThunk 和 Redux Toolkit 时状态不会更新

State will not Update when using createAsyncThunk and Redux Toolkit

当使用createAsyncThunk从我的API获取数据时,我可以读取数据,但状态不会更新。

我在我的文件 userSlice.js 中创建了一个切片,就像这样

userSlice.js:

export const fetchUserById = createAsyncThunk(
  'user/fetchUserById',
  async (userId, thunkAPI) => {
    let response;
    try {
      response = await API.getUser, { userID: userId }));
    } catch (e) {
        console.log(e)
    }
    return response.data.getUser
  }
);

export const userSlice = createSlice({
  name: 'user',
  initialState: {user: {}},
  reducers: {},
  },
  extraReducers: (builder) => {
    builder.addCase(fetchUserById.fulfilled, (state, action) => {
      state = {
        ...state,
        user: action.payload
      }
    });
  }
});

export default userSlice.reducer

这是我的商店,store.js:

import { configureStore } from '@reduxjs/toolkit'
import userReducer from './slices/userSlice'

export default configureStore({
  reducer: {
    userReducer
  }
})

我尝试读取AppLoadingScreen.js

中的数据

AppLoadingScreen.js:

import AppLoading from 'expo-app-loading';
import React from 'react';
import { useSelector, useDispatch } from 'react-redux'
import { fetchUserById } from '../../redux/slices/userSlice';

const AppLoadingScreen = (props) => {
  const user = useSelector(state => state.userReducer.user)
  const dispatch = useDispatch()
  
  const cacheResources = async () => {
    dispatch(fetchUserById('00'))
      .unwrap()
      .then((result) => console.log("result: ", result))
      .then(console.log("in dispatch: ", user))
      .catch((e) => {console.log(e)});

    console.log("test: ", user);
  }

  return (
    <AppLoading
      startAsync={cacheResources}
      onFinish={() => {props.setIsReady(true)}}
      onError={console.warn}
    />
  );
}

输出:

in dispatch:  Object {}
test:  Object {}
result:  Object {
  "firstName": "John",
  "lastName": "Doe",
  "height": 72,
  "age": 40,
}

在这两种情况下,user 都不会更新。即使我将调度调用更改为使用等待,状态也不会改变。 新派遣电话:

const cacheResources = async () => {
  await dispatch(fetchUserById('00'));
  
  console.log("test: ", user);
}

新输出:

test:  Object {}

我也试过运行 Expo 的 AppLoading 组件外的 dispatch 调用,结果还是一样。

state = 在 RTK Immer 动力减速器中永远不会正确。 Immer 的工作方式是跟踪 突变 到嵌套字段 (state.someField =),或者从 reducer 函数 (return newState) 返回一个全新的值。当你写 state = 时,所做的只是将名为 state 的局部变量指向一个新的引用,这既不是突变也不是返回任何东西。

因此,在 Immer 看来,您没有进行任何更改。

这里最简单的答案是写state.user = action.payload

有关详细信息,请参阅 RTK Usage Guides: Writing Reducers with Immer

此外,我们特别推荐not using the word "reducer" in your state structure。相反,您应该设置存储,以便状态键以数据类型命名,例如:

configureStore({
  reducer: {
    user: userReducer
  }
})