0

I implemented a Redux state that stores the boolean value 'isDarkmode': this value changes properly when I click the button, from true to false and viceversa so I implemented redux correctly, I'm sure of it. The problem is that my component SubHeader doesn't change style when I click the button. I report the code below. For example, neither the background or the div below are changing color. Where am I wrong?

SubHeader.tsx

import styles from './SubHeader.module.scss'
import Image from 'next/image'
import sunPic from '../../public/svg/sun.svg'
import { useRouter } from 'next/router'

import { toggleDarkmode } from '../../redux/slices/darkmodeSlice'
import { useAppSelector, useAppDispatch } from '../../redux/hooks'
import { useEffect } from 'react'

 export default function SubHeader() {

    const router = useRouter();
    const isDarkmode = useAppSelector((state) => state.darkmode);
    const dispatch = useAppDispatch();

    const handleChangeLanguage = (language : string) => {
        router.push(router.asPath, router.asPath, { locale: language });
    }

    useEffect (
        () => {
        document.body.style.backgroundColor = isDarkmode ? "#292c35" : "#fff";
      }, [isDarkmode]);


    return (
       
        <div >
            <button 
                className={styles.iconContainer}
                onClick={
                    () => {
                        dispatch(toggleDarkmode());
                        console.log(isDarkmode);
                    }
                }
            >
                <Image 
                    src={sunPic}
                    width={20}
                    height={20}
                    alt={'Dark / Light icon'}
                />
            </button>
            
            <div style={{ background: isDarkmode ? "white" : "yellow" }}></div>
        </div>

    )
}

store.ts

import { configureStore } from '@reduxjs/toolkit'

import darkmodeReducer from './slices/darkmodeSlice'


export const store = configureStore({
  reducer: {
    darkmode: darkmodeReducer
  }
})

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

darkmodeSlice.ts

import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { RootState } from '../store'

// Define a type for the slice state
interface DarkmodeState {
  isDarkmode: boolean
}

// Define the initial state using that type
const initialState: DarkmodeState = {
  isDarkmode : false
}

export const darkmodeSlice = createSlice({
  name: 'darkmode',
  // `createSlice` will infer the state type from the `initialState` argument
  initialState,
  reducers: {
    toggleDarkmode: (state) => {
      state.isDarkmode = !state.isDarkmode;
      localStorage.setItem("isDarkmode", `${state.isDarkmode}`);
    }
  },
})

export const { toggleDarkmode } = darkmodeSlice.actions
 
export default darkmodeSlice.reducer
5
  • Can you also show your slice and the configureStore call? Commented May 2, 2022 at 12:26
  • Sure! I modified the post and reported the code Commented May 2, 2022 at 14:52
  • why don't you use default useSelector & useDispatch hooks from Redux ? Commented May 2, 2022 at 15:21
  • Because I followed the guide of react redux for typescript and it was used these two so I just followed the tutorial Commented May 2, 2022 at 15:34
  • And you are 100% correct to use these hooks like that. Commented May 2, 2022 at 15:59

1 Answer 1

1

Your selector is wrong.

Your darkmode slice has the shape

{
  isDarkmode : boolean
}

and together with your configureStore call that means that your store state has the shape

{
  darkmode: {
    isDarkmode : boolean
  }
}

So your selector const isDarkmode = useAppSelector((state) => state.darkmode); will always select an object of the shape of the slice - but not the boolean value inside that. And the way you are using it, that will always be interpreted as a "truthy" value.

So do

const isDarkmode = useAppSelector((state) => state.darkmode.isDarkmode);

instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfectly right! Thank you a lot, now everything functions in the right way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.