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

Time:01-05

I have this reducer

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;

and want to access the "name" with 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

How do I get the 'name' value after the get request is fulfilled?

Solution:

    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;
        });
    },

then:

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

CodePudding user response:

You can't put the side effect(I/O operations) code inside reducer functions. The redux reducer function should be pure. You should use createAsyncThunk to fetch data.

After your dispatch the async thunk, you should mutate the state with the fetched data inside extraReducers field of createSlice. After mutating the state, the component will re-render, then the useAppSelector will be called. You will read the state fetched from the remote server from the redux store.

E.g.

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>;
}
  •  Tags:  
  • Related