skip to Main Content

I am trying to set initial state of redux slice with a enum value, but it throws Uncaught TypeError: undefined has no properties.

The code is:

export const themeTokenSlice = createSlice({
    name: "themeToken",
    initialState: darkThemeToken,
    reducers: {
        toggleThemeToken: (state) => {
            switch (state.theme) {
                case Themes.dark:
                    state = darkThemeToken;
                    break;
                case Themes.light:
                    state = lightThemeToken;
                    break;
                default:
                    return state;
            }
        }
    }
});

export const darkThemeToken: themeState = {
    theme: Themes.dark
};


export interface themeState {
    theme: Themes;
}

export enum Themes {
    dark = "dark",
    light = "light",
}

The way it works:

export const darkThemeToken: themeState = {
    theme: "dark" as Themes.dark
};

Is there a way to initialize the state with enum?

2

Answers


  1. This is how your code should look like (i think so)
    but you had issues with types, now they should be resolved

    export interface themeState {
      theme: Themes;
      colorPrimary: string,
      colorLink: string,
      colorLinkHover: string,
      colorBgBase: string,
    }
    export enum Themes {
      dark = "dark",
      light = "light",
    }
    export const darkThemeToken: themeState = {
      theme: "dark" as Themes.dark,
      colorPrimary: '#f01879',
      colorLink: '#f01879',
      colorLinkHover: '#f66eab',
      colorBgBase: '#242424',
    };
    export const lightThemeToken: themeState = {
      theme: "dark" as Themes.dark,
      colorPrimary: '#f01879',
      colorLink: '#f01879',
      colorLinkHover: '#f66eab',
      colorBgBase: '#242424',
    };
    export const themeTokenSlice = createSlice({
      name: "themeToken",
      initialState: darkThemeToken,
      reducers: {
          toggleThemeToken: (state: themeState) => {
              switch (state.theme) {
                  case Themes.dark:
                      state = darkThemeToken;
                      break;
                  case Themes.light:
                      state = lightThemeToken;
                      break;
                  default:
                      return state;
              }
          }
      }
    });
    
    
    Login or Signup to reply.
  2. The issues I see in the code:

    • The code attempts to use darkThemeToken and Themes before they are declared. The variables and types should be declared before using them, so move themeState, the Themes enum, and darkThemeToken and lightThemeToken declarations above the themeTokenSlice slice declaration where they are referenced.

    • The toggleThemeToken reducer is reassigning the state. In Redux-Toolkit you can either mutate the current state or return new state, never both, and never reassign the state a different value.

      Examples:

      state.theme = Themes.dark;
      
      state.theme = Themes.light;
      
      return darkThemeToken;
      
      return lightThemeToken;
      
    • There is a logical issue/bug where you are returning the "dark theme" value when the current state is already the dark theme, and vice-versa for the light theme. These values should be inverted, i.e. if the current state is the dark theme, then update to the light theme.

    Example Refactor:

    themeToken.slice.ts

    import { createSlice } from "@reduxjs/toolkit";
    
    export enum Themes {
      dark = "dark",
      light = "light",
    }
    
    export interface themeState {
      theme: Themes;
    }
    
    const initialState: themeState = {
      theme: Themes.dark,
    };
    
    const themeTokenSlice = createSlice({
      name: "themeToken",
      initialState,
      reducers: {
        toggleThemeToken: (state) => {
          // switch (state.theme) {
          //   case Themes.dark:
          //     state.theme = Themes.light;
          //     break;
          //   case Themes.light:
          //     state.theme = Themes.dark;
          //     break;
          //   default:
          //     // do nothing
          // }
    
          state.theme = state.theme === Themes.dark ? Themes.light : Themes.dark;
        },
      },
    });
    
    export const { toggleThemeToken } = themeTokenSlice.actions;
    
    export default themeTokenSlice.reducer;
    

    Demo

    Edit sweet-platform

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search