Home > Blockchain >  Why is useSelector is always returning undefined? using React.js Redux Toolkit Redux Persist
Why is useSelector is always returning undefined? using React.js Redux Toolkit Redux Persist

Time:12-15

`I am building a small calculator. I am trying to store the data from each input locally. My approach was to combine redux toolkit with redux-persist. Everything seems to be working fine, I get no errors. My store is updating and persisting on refresh. However on using useSelector it always returns as undefined, using redux devtools I can see that the value I am trying to grab exists.

Main.js (entrypoint)

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import { store } from "./store/store";
import { PersistGate } from "redux-persist/integration/react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import { persistStore } from "redux-persist";

let persistor = persistStore(store);

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <App />
      </PersistGate>
    </Provider>
  </React.StrictMode>
); 

roiCalculationSlice.jsx

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

const initialState = {
  shifts: 0,
  rate: 0,
  machines: 0,
  numberOfDaysPerWeek: 0,
  numberOfWeeksPerYear: 0,
};

export const roiCalculationSlice = createSlice({
  name: "roi",
  initialState,
  reducers: {
    shiftsReducer: (state, action) => {
      state.shifts = action.payload.shifts;
    },
    hoursReducer: (state, action) => {
      state.hoursPerShift = action.payload.hours;
    },
    rateReducer: (state, action) => {
      console.log(action.payload, "payload");
      state.rate = action.payload;
    },
    daysReducer: (state, action) => {
      state.numberOfDaysPerWeek = action.payload.numberOfDaysPerWeek;
    },
    weeksReducer: (state, action) => {
      state.numberOfWeeksPerYear = action.payload.numberOfWeeksPerYear;
    },
    machineReducer: (state, action) => {
      state.machines = action.payload.machines;
    },
  },
});


// Action creators are generated for each case reducer function
export const {
  rateReducer,
  shiftsReducer,
  hoursReducer,
  weeksReducer,
  machineReducer,
} = roiCalculationSlice.actions;

export default roiCalculationSlice.reducer;

FirstStep.jsx (component)

import { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
import CustomButton from "./../components/buttons/CustomButton";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Logo from "../assets/transor-modified.png";
import { useDispatch, useSelector } from "react-redux";
import "./firstStep.css";
import {
  hoursReducer,
  rateReducer,
  shiftsReducer,
} from "../store/features/roiCalculationSlice";

function FirstStep() {
  const dispatch = useDispatch();
  // This useSelector returns undefined
  const storeRate = useSelector((store) => {
    store.roi.rate;
  });
  // This useSelector returns undefined
  console.log(storeRate, "useSelector result");

  const [shifts, setshifts] = useState(0);
  const [days, setDays] = useState(0);
  const [rate, setRate] = useState(0);

  const onRateChange = (e) => {
    dispatch(rateReducer(e.currentTarget.value));
  };

  return (
    <Container>
      <Row className="justify-content-end">
        <Col xs={3}>
          <img className="img-fluid" src={Logo} alt="transor logo" />
        </Col>
      </Row>
      <Row>
        <Col>
          <h1 className="firststep-title">STEP 1 </h1>
        </Col>
      </Row>
      <Row>
        <Col>
          <label className="firststep-label" htmlFor="shifts">
            NUMBER OF SHIFTS
          </label>
          <br />
          <input
            onChange={(e) => {
              setshifts(e.currentTarget.value);
            }}
            className="calculation-input"
            type="number"
            id="shifts"
            name="shifts"
          />
        </Col>
      </Row>
      <Row>
        <Col>
          <label className="firststep-label" htmlFor="shifts">
            $ PER HOUR
          </label>
          <br />
          <input
            className="calculation-input"
            type="text"
            onChange={(e) => setRate(e.currentTarget.value)}
          />
        </Col>
      </Row>
      <Row>
        <Col>
          <label className="firststep-label" htmlFor="shifts">
            HOURS PER DAY
          </label>
          <br />
          <input
            onChange={(e) => {
              setDays(e.currentTarget.value);
            }}
            className="calculation-input"
            type="number"
            id="shifts"
            name="shifts"
          />
        </Col>
      </Row>

      <Row>
        <Col>
          <CustomButton className="custom-button-home">
            <NavLink className="custom-button-home" to="/secondstep">
              Next
            </NavLink>
          </CustomButton>
        </Col>
      </Row>
      <Row>
        <Col>
          <CustomButton className="custom-button-home ">
            <NavLink className="custom-button-home" to="/getstarted">
              Back
            </NavLink>
          </CustomButton>
        </Col>
      </Row>
    </Container>
  );
}

export default FirstStep;

An image of my redux devtools   console.log results

CodePudding user response:

You need to return the value from useSelector. You may try the following

useSelector((store) => {
   return store.roi.rate;
});
  • Related