Redux Toolkit for calculator challenge?

Tell us what’s happening:
I examined the boilerplate in a project file created with npm create-react-app --template redux. It included an example implementation of a counter app using the redux toolkit, a library not really addressed in the course material. I decided to have a go at it anyway and tried my best to mimic the boilerplate’s syntax with my calculator logic, being careful to rename and refactor each element of the boilerplate to fit my particular project. Specifically, it implemented something called a slice which, if I understand the docs correctly, should be automatically creating action creators and state-immutable reducer functions that correspond with the elements you declare in the reducers field of the slice object. Kinda sounded too good to be true and so far seems to be. Here’s the slice I currently have. The render element itself just has a bunch of css-arranged button elements and a display that call useDispatch(reducerElement) where reducerElement is an item in the reducers property of the slice.

Your code so far

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


const initialState = {
  display: '0',
  currentOperand: null,
  previousOperand: null,
  currentOperator: null
};


export const calculatorSlice = createSlice({
  name: 'calculator',
  initialState,
  reducers: {
    getDisplay: (state) => {
      return state.display;
    },
    enterDigit: (state, action) => {
      if(state.display != '0'){
        [...state.display].concat(action.payload);     
      } else { 
        state.display = action.payload;
      }
      state.currentOperand = parseFloat(state.display);
    },
    enterDecimal: (state) => {
      if(state.display.includes('.') == false){
        [...state.display].concat('.');
      }
      state.currentOperand = state.display;
    },
    
    add: (state) => {
      if(state.currentOperand != null && state.previousOperand == null){
        state.previousOperand = state.currentOperand;
        state.currentOperand = 0;
        state.display = '0';
      } else if (state.previousOperand != null){
        state.display = (state.previousOperand + state.currentOperand).toString();
        state.currentOperand = state.previousOperand;
        state.display = parseFloat(state.display);
      } else { state.previousOperand = 0 }
      state.currentOperator = '+'; 
    },
    subtract: (state) => {
      if(state.currentOperand != null && state.previousOperand == null){
        state.previousOperand = state.currentOperand;
        state.currentOperand = 0;
        state.display = '0';
      } else if (state.previousOperand != null){
        state.display = (state.previousOperand - state.currentOperand).toString();
        state.currentOperand = state.previousOperand;
        state.display = parseFloat(state.display);
      } else { state.previousOperand = 0 }
      state.currentOperator = '-'; 
    },
    multiply: (state) => {
      if(state.currentOperand != null && state.previousOperand == null){
        state.previousOperand = state.currentOperand;
        state.currentOperand = 0;
        state.display = '0';
      } else if (state.previousOperand != null){
        state.display = (state.previousOperand * state.currentOperand).toString();
        state.currentOperand = state.previousOperand;
        state.display = parseFloat(state.display);
      } else { state.previousOperand = 0 }
      state.currentOperator = '*'; 
    },
    divide: (state) => {
      if(state.currentOperand != null && state.previousOperand == null){
        state.previousOperand = state.currentOperand;
        state.currentOperand = 0;
        state.display = '0';
      } else if (state.previousOperand != null){
        state.display = (state.previousOperand / state.currentOperand).toString();
        state.currentOperand = state.previousOperand;
        state.display = parseFloat(state.display);
      } else { state.previousOperand = 0 }
      state.currentOperator = '/'; 
    },
    equals: (state) => {
      if(state.currentOperand != null && state.previousOperand != null){
        switch(state.currentOperator){
          case '+': state.display = (state.previousOperand + state.currentOperand).toString();
            state.currentOperand = parseFloat(state.display);
            state.previousOperand = null;
            break;
          case '-': state.display = (state.previousOperand - state.currentOperand).toString();
            state.currentOperand = parseFloat(state.display);
            state.previousOperand = null;
            break;
          case '*': state.display = (state.previousOperand * state.currentOperand).toString();
            state.currentOperand = parseFloat(state.display);
            state.previousOperand = null;
            break;
          case '/': state.display = (state.previousOperand / state.currentOperand).toString();
            state.currentOperand = parseFloat(state.display);
            state.previousOperand = null;
            break;
          default: state.display = state.currentOperand.toString();
        }
      } else if (state.currentOperator != null && state.previousOperand == null){
        state.display = state.currentOperand.toString();
      } else { state.display = '0' }
      state.currentOperator = null;
    },
    clear: (state) => {
      state.display = '0';
      state.currentOperand = null;
      state.previousOperand = null;
      state.currentOperator = null;
    }
  }
});

export const { getDisplay, enterDigit, enterDecimal, add, subtract, multiply, divide, equals, clear } = calculatorSlice.actions;
export const selectDisplay = (state) => state.display;


export default calculatorSlice.reducer;

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36

Challenge: Build a JavaScript Calculator

Link to the challenge:

For clarity, here is the code for my render function. I’m getting the buttons to render successfully, but none of the action dispatches seem to be working, so the problem is seemingly in the react-redux layer or beyond into the redux layer.


import { useDispatch } from 'react-redux';


import {
  getDisplay,
  enterDigit,
  enterDecimal,
  add,
  subtract,
  multiply,
  divide,
  equals,
  clear,
  selectDisplay,
} from './calculatorSlice';


export function Calculator() {
  
  
  

  return (
    <div id='wrapper'>
      <h1 id='display'>{useDispatch(getDisplay)}</h1>
        <div id='numpad'>
          <button id='one' onClick={useDispatch(enterDigit('1'))}>1</button>
          <button id='two' onClick={useDispatch(enterDigit('2'))}>2</button>
          <button id='three' onClick={useDispatch(enterDigit('3'))}>3</button>
          <button id='plus' onClick={useDispatch(add)}>+</button>
          <button id='four' onClick={useDispatch(enterDigit('4'))}>4</button>
          <button id='five' onClick={useDispatch(enterDigit('5'))}>5</button>
          <button id='six' onClick={useDispatch(enterDigit('6'))}>6</button>
          <button id='minus' onCLick={useDispatch(subtract)}>-</button>
          <button id='seven' onClick={useDispatch(enterDigit('7'))}>7</button>
          <button id='eight' onClick={useDispatch(enterDigit('8'))}>8</button>
          <button id='nine' onClick={useDispatch(enterDigit('9'))}>9</button>
          <button id='multiply' onClick={useDispatch(multiply)}>*</button>
          <button id='decimal' onClick={useDispatch(enterDecimal)}>.</button>
          <button id='zero' onClick={useDispatch(enterDigit('0'))}>0</button>
          <button id='clear' onClick={useDispatch(clear)}>clear</button>
          <button id='divide' onClick={useDispatch(divide)}>/</button>
        </div>
        <button id='equals' onClick={useDispatch(equals)}>=</button>
    </div>
  );
}

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.