createAsyncThunk 的问题

Problems with createAsyncThunk

我刚刚在 Codecademy 上完成了 Learn Redux,想在实践中掌握这些知识。但是我有一个错误。当我创建 extraReducers 以将状态更新为实际承诺状态时,它不会添加信息。

getUserSlice.js

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchUserInfo } from '../../api';

export const loadUser = createAsyncThunk("getUser/loadUser",
    async (arg, thunkAPI) => {
        return await fetchUserInfo();
        
    }
});
const sliceOptions = {
  name: 'getUser',
  initialState: {
    info: [],
    isLoading: false,
    hasError: false,
  },
  reducers: {},
   extraReducers: (builder) => {
        builder
            .addCase(loadUser.pending, (state) => {
            state.isLoading = true;
            state.hasError = false;
            })
            .addCase(loadUser.fulfilled, (state, action) => {
            state.info.push(action.payload)
            
            state.isLoading = false;
            state.hasError = false;
            })
            .addCase(loadUser.rejected, (state, action) => {
            state.isLoading = false;
            state.hasError = true;
            })
    },
};

export const getUserSlice = createSlice(sliceOptions);
console.log(getUserSlice);

export const selectUserInfo = (state) => {
  console.log(state);
  return state;
};

export default getUserSlice.reducer;

api.js

export const fetchUserInfo = async () => {
   const user = await fetch('http://localhost:5000/api/user');
   const json = user.json();

   return json;
}

App.js

import React from 'react';
import './App.css';

import {Container} from 'react-bootstrap';
import Achievement from './components/Achievement/Achievement';
import { useSelector } from 'react-redux';
import { selectUserInfo } from './features/getUser/getUserSlice';



const colors = ['#010626','#4d6396', '#5d1a87', '#5d1a87', '#5d1a87'];

function App() {
 
   
  let color= colors[0];
  const user = useSelector(selectUserInfo)
  function changeColor() {
    const newColor = `rgb(${Math.round(Math.random() *256)}, ${Math.round(Math.random() *256)}, ${Math.round(Math.random() *256)})`;
    
    color = newColor;
  }
  
    return (
      <div className="App" style={{ background: color }}>
          <Container>
            <h1 id="whoAmI">
              Witaj na moim portfolio
              {user}
            </h1>
            <button onClick={changeColor}>
              Zmień kolor tła
            </button>
            <div className="col-lg-4 col-md-6 col-sm-12">
              <Achievement title="Ukończenie The Web Developer Bootcamp" picture="https://res.cloudinary.com/syberiancats/image/upload/v1630317595/k9g0nox2fyexxawg8whu.jpg" />
            </div>
          </Container>
         
         
      </div>
    );
  

  
  
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import reportWebVitals from './reportWebVitals';
import { store } from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);


reportWebVitals();

store.js

import { configureStore } from "@reduxjs/toolkit";
import getUserReducer from "./features/getUser/getUserSlice";

export const store = configureStore({
    reducer: {
        getUser: getUserReducer
    }
})

Console.log 的 getUserSlice 和选择器中的状态

也许您可以在 extraReducer 中使用 (builder) => {} 函数并编辑您的 loadUser 因为您的 Api.js 已经 return json 代码以下:

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchUserInfo } from '../../api';

export const loadUser = createAsyncThunk('getUser/loadUser', async (arg, thunkAPI) => {
  return await fetchUserInfo();
});
const sliceOptions = {
  name: 'getUser',
  initialState: {
    info: [],
    isLoading: false,
    hasError: false,
  },
  reducers: {},
  extraReducers: (builder) => {
  builder
    .addCase(loadUser.pending, (state) => {
     state.isLoading = true;
     state.hasError = false;
    })
    .addCase(loadUser.fulfilled, (state, action) => {
     state.info.push(action.payload)
     
     state.isLoading = false;
     state.hasError = false;
    })
    .addCase(loadUser.rejected, (state, action) => {
     state.isLoading = false;
     state.hasError = true;
    })
  },
};

export const getUserSlice = createSlice(sliceOptions);
console.log(getUserSlice);

export const selectUserInfo = (state) => {
  console.log(state);
  return state;
};

export default getUserSlice.reducer;

你可能忘记在fetch之前添加await,你应该将api.js中的抓取数据编辑成下面这样:

export const fetchUserInfo = async () => {
   const user = await fetch('http://localhost:5000/api/user');
   const json = user.json();

   return json;
}

您可以隐式 return 并绕过 Promise 结果。类似于:

 (arg, thunkAPI) => fetchUserInfo();
        

但是,我会采取“循序渐进”的方式

export const loadUser = createAsyncThunk("getUser/loadUser",
    async (arg, tunkApi) => {
        try {
           const response = await fetchUserInfo();
           return response;
        } catch (e) {
          return thunkApi.rejectWithValue(e)
        }
    }
});