Reputation: 27
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
Upvotes: 0
Views: 325
Reputation: 44106
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.
Upvotes: 1