Search code examples
reactjsreduxreact-reduxredux-toolkitredux-thunk

Redux toolkit TypeError: Cannot read properties of undefined (reading 'type') while fetching data with redux thunk


I need to fetch data from my API with redux thunk and axios. but I'm facing this error inside my console.

ERROR IMAGE

In this case I have a marketSlice and I want to update my state.market with API Data.

marketSlice.js

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

// Thunk action to fetch data from the server
export const fetchMarketData = (requestData) => createAsyncThunk(
  'market/fetchData', () => {
    const url = 'http://localhost:8000/api/market'
    const headers = {
      'Content-Type': 'application/json',
    };
    return axios
      .post(url, requestData, {headers})
      .then(response => response.data)
  }
);

export const marketSlice = createSlice({
  name: 'market',
  initialState: {
    market: null,
    loading: false,
    error: '',
  },
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(fetchMarketData.pending, (state) => {
        state.loading = true;
        state.error = null;
    })
    builder.addCase(fetchMarketData.fulfilled, (state, action) => {
        state.loading = false;
        state.market = action.payload
    })
    builder.addCase(fetchMarketData.rejected, (state) => {
        state.loading = false;
        state.error = "Request Failed.";
    });
  },
});

store.js

import { configureStore } from '@reduxjs/toolkit'
import { marketSlice } from './marketSlice.js'

export const store = configureStore({
  reducer: {
    market: marketSlice.reducer
  },
  middleware: (getDefaultMiddleware)=> getDefaultMiddleware({
    serializableCheck: false,
  }),
})

App.jsx

import { useDispatch } from 'react-redux'
import { useEffect } from 'react'
import { fetchMarketData } from './redux/marketSlice.js'

export default function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    const requestData = {
      exchange: "binance"
    }
    dispatch(fetchMarketData(requestData));

  }, [dispatch]);

  return (
    <>
        Something...
    </>
  )

}

Solution

  • You seem to have coded fetchMarketData to be a function that returns the asynchronous thunk action creator function instead just being the returned generated thunk action itself. Based on usage I would say you intended for the requestData to be the argument passed to the action payload creator.

    Incorrect

    export const fetchMarketData = (requestData) => createAsyncThunk(
      'market/fetchData',
      () => {
        const url = 'http://localhost:8000/api/market'
        const headers = {
          'Content-Type': 'application/json',
        };
        return axios
          .post(url, requestData, { headers })
          .then(response => response.data);
      }
    );
    

    Correct

    export const fetchMarketData = createAsyncThunk(
      'market/fetchData',
      (requestData, thunkApi) => { // <-- arg passed here
        const url = 'http://localhost:8000/api/market';
        const headers = {
          'Content-Type': 'application/json',
        };
        return axios
          .post(url, requestData, { headers })
          .then(response => response.data)
          .catch(error => thunkApi.rejectWithValue(error));
      }
    );
    

    or

    export const fetchMarketData = createAsyncThunk(
      'market/fetchData',
      async (requestData, thunkApi) => { // <-- arg passed here
        const url = 'http://localhost:8000/api/market';
        const headers = {
          'Content-Type': 'application/json',
        };
    
        try {
          const { data } = axios.post(url, requestData, { headers });
          return data;
        } catch(error) {
          return thunkApi.rejectWithValue(error);
        }
      }
    );