blowecle
blowecle

Reputation: 11

useSelector() providing initial state instead of updated state

I am using redux along with react-redux and unable to use the useSelector() function to access the updated value. My middleware shows state updating properly. I have wrapped my app in a Provider and passed in my store.

My reducers are working correctly, my middleware shows the correct updated state, and console.logs I have put inside the thunks are firing and returning the correct data, however my useSelector is returning my initial state.

Artifact Slice

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
const axios = require('axios');

const artifactSlice = createSlice({
    name: 'artifactList',
    initialState: {
        artifacts: [],
        artifactData: {},
        status: 'idle',
        error: null,
        filter: null,
    },
    reducers: {
        getArtifactList: (state, action) => {
            state.artifactList = action.payload;
            return state;
        },
        getArtifact: (state, action) => {
            state.artifactData = action.payload;
            return state;
        },
        setErrorMsg: (state, action) => {
            state.errorMsg = action.payload;
            return state;
        },
        extraReducers(builder) {
            builder
                .addCase(fetchArtifacts.pending, (state, action) => {
                    state.status = 'loading';
                })
                .addCase(fetchArtifacts.fulfilled, (state, action) => {
                    state.status = 'succeeded';
                    state.artifacts = action.payload;
                })
                .addCase(fetchArtifactData.pending, (state, action) => {
                    state.status = 'loading';
                })
                .addCase(fetchArtifactData.fulfilled, (state, action) => {
                    state.status = 'succeeded';
                    state.artifactData = action.payload;
                })
        }
    }
});

export default artifactSlice.reducer;

export const {
    getArtifactList,
    getArtifact,
    setErrorMsg,
} = artifactSlice.actions;

export const fetchArtifacts = createAsyncThunk('artifacts/fetchArtifacts', async () => {
    try {
        const { data } = await axios.get('http://localhost:3000/api/');
        console.log("DATA: ", {data})
        return data;
    } catch (e) {
        console.log(e);
    }
});

export const fetchArtifactData = createAsyncThunk('/artifacts/fetchArtifactData', async (id) => {
    try {
        const { data } = await axios.get(`http://localhost:3000/api/artifacts/${id}`);
        console.log("DATA: ", {data})
        return data;
    } catch (e) {
        console.log(e);
    }
})

These console logs are returning the expected values.

Create Store

import artifactReducer from './reducers/artifactSlice';
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import loggerMiddleware from "redux-logger";

export default configureStore({
    reducer: {
        artifact: artifactReducer,
    },
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware().concat(loggerMiddleware),
})

Fetching Store

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { ReactCompareSlider, ReactCompareSliderImage } from 'react-compare-slider';
import '../../css/Home.css'
import { Link } from 'react-router-dom';
import Artifact from './Artifact';
import Slider from '../slider/Slider';
import { fetchArtifacts } from '../../store/reducers/artifactSlice';

const Home = () => {
    const dispatch = useDispatch();

    
    useEffect(() => {
        // const asyncFetchArtifacts = async () => {
        //     const fetchAllArtifacts = await dispatch(fetchArtifacts());
        // }
        //  const artifactData = asyncFetchArtifacts();
        // console.log(artifacts)
        dispatch(fetchArtifacts())
    },[])
    
    const artifactData = useSelector(state => state);

    console.log(artifactData)
return (rest of my html in here)

When I try to console.log(artifactData) it returns only my initial state.

EDIT: It seems like my useSelector is not running after the useEffect runs.

Upvotes: 0

Views: 759

Answers (1)

Marcia Moss
Marcia Moss

Reputation: 225

extraReducers placement needs to be outside reducers within slice so like this:

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

const artifactSlice = createSlice({
  name: "artifactList",
  initialState: {
    artifacts: [],
    artifactData: {},
    status: "idle",
    error: null,
    filter: null,
  },
  reducers: {
    getArtifactList: (state, action) => {
      state.artifactList = action.payload;
      return state;
    },
    getArtifact: (state, action) => {
      state.artifactData = action.payload;
      return state;
    },
    setErrorMsg: (state, action) => {
      state.errorMsg = action.payload;
      return state;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchArtifacts.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchArtifacts.fulfilled, (state, action) => {
        state.status = "succeeded";
        state.artifacts = action.payload;
      })
      .addCase(fetchArtifactData.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchArtifactData.fulfilled, (state, action) => {
        state.status = "succeeded";
        state.artifactData = action.payload;
      });
  },
});

export default artifactSlice.reducer;

export const { getArtifactList, getArtifact, setErrorMsg } =
  artifactSlice.actions;

export const fetchArtifacts = createAsyncThunk(
  "artifacts/fetchArtifacts",
  async () => {
    try {
      const { data } = await axios.get(
        "http://localhost:3000/api/"
      );
      console.log("DATA: ", { data });
      return data;
    } catch (e) {
      console.log(e);
    }
  }
);

export const fetchArtifactData = createAsyncThunk(
  "/artifacts/fetchArtifactData",
  async (id) => {
    try {
      const { data } = await axios.get(
        `http://localhost:3000/api/artifacts/${id}`
      );
      console.log("DATA: ", { data });
      return data;
    } catch (e) {
      console.log(e);
    }
  }
);

Upvotes: 1

Related Questions