如何让 useAppSelector 等待来自 Get 请求的数据(而不是显示初始数据)

how to make useAppSelector wait for data from Get request (instead of showing initial data)

我有这个减速器

import { createSlice } from "@reduxjs/toolkit";

export const projectSlice = createSlice({
name: "project-redux",
initialState: {
    name: "",
},
reducers: {
    get_project: (state, action) => {
    axios
        .get("http://localhost:5000/api/project/" + action.payload)
        .then((res) => {
        state = res.data; //which contains the name
    
        });
    },
},
});

export const { get_project } = projectSlice.actions;

export default projectSlice.reducer;

并想使用 useAppSelector

访问“名称”
const dispatch = useAppDispatch();

const {name}=useAppSelector(state=>state.projs) //projs is the name of projectsReducer in the store
console.log(name) // only give initial state

get请求完成后如何获取'name'值?

解决方案:

    export const fetchProject = createAsyncThunk(
    "fetchProject",
    async (id) => {
        const res = await axios.get("http://localhost:5000/api/project/" + id);

        return res.data.title;
    }
    );
  reducers: {//other reducers if ther is}
  extraReducers: (builder) => {
        builder.addCase(fetchProject.fulfilled, (state, action) => {
        state.title = action.payload;
        });
    },

然后:

const name = useAppSelector((state) => state.projs.title);
console.log("selecttitle", name);

您不能将副作用(I/O 操作)代码放入 reducer 函数中。 redux reducer 函数应该是纯的。您应该使用 createAsyncThunk 来获取数据。

分派异步 thunk 后,您应该使用 createSliceextraReducers 字段中获取的数据改变状态。改变状态后,组件将重新渲染,然后 useAppSelector 将被调用。您将从 redux 存储中读取从远程服务器获取的状态。

例如

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

import { useEffect } from 'react';

export const fetchProject = createAsyncThunk('fetchProject', (id) => {
  return axios.get('http://localhost:5000/api/project/' + id).then((res) => res.data);
});

export const projectSlice = createSlice({
  name: 'project-redux',
  initialState: {
    name: '',
  },
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(fetchProject.fulfilled, (state, action) => {
      state.name = action.payload;
    });
  },
});

export default projectSlice.reducer;

// Component

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
function Test() {
  const dispatch = useDispatch();
  const { name } = useSelector((state) => state.projs);
  useEffect(() => {
    dispatch(fetchProject('1'));
  }, [dispatch]);

  return <div>{name}</div>;
}