0

I cannot seem to see what is going wrong here, pretty basic usage to useContext and useState hooks. I have a darkModeContext where I am literally just flipping the boolean for darkMode, but whilst trying to flip it for the context I am getting setContext is not a function.

I took some code out from the navDrawer to make it easier to see but here is the error I am getting along with the code: error in console - the boolean is flipped but cannot be passed to setDarkTheme withour erroring

DarkThemeContext.js

import React from "react";

const DarkThemeContext = React.createContext({
    darkMode: false,
    setDarkMode:() => {},
});

export default DarkThemeContext

DarkThemeSwitcher.js

import React, { useContext } from 'react';
import { IconButton, Tooltip } from '@material-ui/core';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import LightThemeIcon from '@material-ui/icons/Brightness7';
import DarkThemeIcon from '@material-ui/icons/Brightness4';

import DarkThemeContext from '../DarkThemeContext/DarkThemeContext';

const DarkThemeSwitcher = () => {
    const useStyles = makeStyles((theme) => ({
        darkThemeButton: {
            background: "none",
            border: "none",
        },
        darkThemeMobileButton: {
            [theme.breakpoints.up('sm')]: {
                display: "none",
            },
            [theme.breakpoints.down('sm')]: {
                background: "none",
                border: "none",
                display: "visible",
                paddingLeft: theme.spacing(2),
                minWidth: '25%'

            },
        },
        menuHeaderText: {
            minWidth: '97%',
        }
    }));



    const classes = useStyles();
    const { darkMode, setDarkMode } = useContext(DarkThemeContext);

    const handleLightThemeToggle = () => {
        console.log(!darkMode)
        setDarkMode(!darkMode);
    };

    return (
        darkMode ?
            <Tooltip title="Light Mode" className={classes.darkThemeMobileButton} onClick={handleLightThemeToggle} >
                <IconButton aria-label="Light Mode">
                    <DarkThemeIcon />
                </IconButton>
            </Tooltip >
            :
            <Tooltip title="Dark Mode" className={classes.darkThemeMobileButton} onClick={handleLightThemeToggle} >
                <IconButton aria-label="Dark Mode">
                    <LightThemeIcon />
                </IconButton>
            </Tooltip>

    )
}

export default DarkThemeSwitcher;

NavDrawer.js

import React from 'react';
import DarkThemeContext from '../DarkThemeContext/DarkThemeContext';
import DarkThemeSwitcher from '../DarkThemeSwitcher/DarkThemeSwitcher';

const NavDrawer = ({ children, window }) => {
    const classes = useStyles();
    const theme = useTheme();
    const [mobileOpen, setMobileOpen] = React.useState(false);
    const [darkTheme, setDarkTheme] = React.useState(false);
    const value = { darkTheme, setDarkTheme };

const container = window !== undefined ? () => window().document.body : undefined;

    return (
        <DarkThemeContext.Provider value={value}>
            <ThemeProvider theme={darkThemeStyling}>
                <div className={classes.root}>
                    <CssBaseline />
                    <AppBar position="fixed" className={classes.appBar}>
                        <Toolbar>
                            <IconButton
                                color="inherit"
                                aria-label="open drawer"
                                edge="start"
                                onClick={handleDrawerToggle}
                                className={classes.menuButton}
                            >
                                <MenuIcon />
                            </IconButton>
                            <Typography className={classes.menuHeaderText} variant="h6" noWrap>
                                My app
                            </Typography>
                            <DarkThemeSwitcher/>
                        </Toolbar>
                    </AppBar>
                    <nav className={classes.drawer} aria-label="navigation links">
                        <Hidden smUp implementation="css">
                            <SwipeableDrawer
                                container={container}
                                variant="temporary"
                                anchor={theme.direction === 'rtl' ? 'right' : 'left'}
                                open={mobileOpen}
                                onClose={handleDrawerToggle}
                                classes={{
                                    paper: classes.drawerPaper,
                                }}
                                ModalProps={{
                                    keepMounted: true, // Better open performance on mobile.
                                }}
                            >
                                {drawer}
                            </SwipeableDrawer>
                        </Hidden>
                        <Hidden xsDown implementation="css">
                            <Drawer
                                classes={{
                                    paper: classes.drawerPaper,
                                }}
                                variant="permanent"
                                open
                            >
                                {drawer}
                            </Drawer>
                        </Hidden>
                    </nav>
                    <main className={classes.content}>
                        <div className={classes.toolbar} />
                        {children}
                        {console.log(value)}
                    </main>
                </div>
            </ThemeProvider>
        </DarkThemeContext.Provider>
    );
}
export default NavDrawer;
user2921885
  • 159
  • 11

1 Answers1

2

You have different keys in DarkThemeContext and in NavDrawer when you initialize the values, i.e. darkTheme vs darkMode.

Rename in NavDrawer should resolve the error.

    // In NavDrawer
    const [darkMode, setDarkMode] = React.useState(false);
    const value = { darkMode, setDarkMode };
Claire Lin
  • 2,372
  • 8
  • 13
  • Ty <3 I can't seem to keep the context however when navigating between pages... Should something like this work in navBar (root level of app): const [darkMode, setDarkMode] = React.useState(darkMode ? darkMode : false);... it always goes to false because of const [darkMode, setDarkMode] = React.useState(false); – user2921885 Jun 14 '21 at 20:15
  • Since `DarkThemeContext.Provider` is in NavDrawer, that's the root from which your context is available. Any descendants of this component has the access to the theme value, but not siblings nor any other part of your app. If you need it in `NavBar`, assuming that's an ancestor of `NavDrawer`, you need to move the context provider to `NavBar` and set state there. – Claire Lin Jun 14 '21 at 20:34