Home > OS >  Why is my data not loading into redux store?
Why is my data not loading into redux store?

Time:04-17

I have a react app that was working until I converted over to a nextjs app. The axios call is being made, the data is being returned but not being stored(the selectors are showing undefined). I suspect it is a setup issue in the conversion.

The call which works:

React.useEffect(() => {
    dispatch(fetchCoinsByMarketCap()); // coin gecko
  }, [dispatch]);

The slice. I am logging correct data and status in my fetchCoinsByMarketCap.fulfilled case:

import axios from "axios";
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { coinGecko } from "../../url/urlList";
const initialState = {
  coinsMCap: [],
  status: "idle",
  error: null,
};

export const fetchCoinsByMarketCap = createAsyncThunk(
  "coinsByMarketCap/fetchCoinsByMarketCap",
  async () => {
    const res = await coinGecko.get(
      `/coins/markets/? 
vs_currency=usd&order=market_cap_desc&per_page=50&page=1&sparkline=false`
    );
    return res.data;
  }
);

export const marketCapSlice = createSlice({
  name: "coinsByMarketCap",
  initialState,
  reducers: {
    updateCoinsMcapState: (state, action) => {
      Object.assign(state, action.payload);
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchCoinsByMarketCap.pending, (state) => {
        state.status = "loading";
      })
      .addCase(fetchCoinsByMarketCap.fulfilled, (state, action) => {
        state.coinsMCap = action.payload;
        state.status = "succeeded";
        console.log("sc: ", state.coinsMCap);
        console.log("ss: ", state.status);
      })
      .addCase(fetchCoinsByMarketCap.rejected, (state, action) => {
        state.status = "failed";
        state.error = action.error.message;
      });
  },
});

export const { updateCoinsMcapState } = marketCapSlice.actions;
export default marketCapSlice.reducer;

My store:

import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createWrapper } from "next-redux-wrapper";
import reducer from "./rootReducer";

const middleware = [thunk];
const makeStore = () =>
  createStore(reducer, compose(applyMiddleware(...middleware)));

export const wrapper = createWrapper(makeStore);

The next _app file which has the wrapper.withRedux export:

import React from "react";
import { wrapper } from "../redux/store";

const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;

export default wrapper.withRedux(MyApp);

The root reducer:

import { combineReducers } from "redux";
import marketCapReducer from "./slices/marketCapSlice";


const reducer = combineReducers({
  coinsByMarketCap: marketCapReducer,
});

export default reducer;

The selector file:

// marketCapSlice selectors
export const selectCoinsMCap = (state) => state.coinsByMarketCap.coinsMCap;
export const selectCoinsMCapStatus = (state) => state.coinsByMarketCap.status;
export const selectCoinsMCapError = (state) => state.coinsByMarketCap.error;

These selectors should have data after the axios call, but they don't. Again bear in mind that this used to work before I tried to convert it to next and the only thing I changed was the store and the _app.js files. The old store without next was very simple:

import { configureStore } from "@reduxjs/toolkit";
import reducer from "./rootReducer";

const store = configureStore({ reducer });
export default store;

And the standard provider setup in the old index:

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

Maybe one of you nextjs experts can help me.

CodePudding user response:

A reducer is supposed to return the updated state, as far as I know. It seems to me like you may have forgotten to return a value here:

 reducers: {
    updateCoinsMcapState: (state, action) => {
      Object.assign(state, action.payload);
    },
  },

Should it be something like this?

 reducers: {
    updateCoinsMcapState: (state, action) => {
      return Object.assign(state, action.payload);
    },
  },

CodePudding user response:

Here is the store setup that fixed it:

import { configureStore } from "@reduxjs/toolkit";
import { applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createWrapper } from "next-redux-wrapper";
import reducer from "./rootReducer";

const middleware = [thunk];

const makeStore = () =>
  configureStore({ reducer }, compose(applyMiddleware(...middleware)));

export const wrapper = createWrapper(makeStore);

I used configureStore instead of createStore and enclosed reducer in curly braces.

  • Related