Почему я не могу прочитать эту тему React Material в своем коде

Я учусь реагировать, и теперь у меня есть эта тема, которая не работает.

Этот код работает нормально, я могу переключаться между 10 различными темами:

    import React, { createContext, useState, useEffect } from 'react';
    import { ThemeProvider } from '@material-ui/styles';
    import allThemes from './index';
    
    const ThemeContext = createContext({});
    const lastThemeIndex = allThemes.length - 1;
    const ThemeContextProvider = props => {
        const [theme, setTheme] = useState();
        const [themeName, setThemeName] = useState(allThemes[0].name);
    
        const setThemeType = () => {
            const themeIndex = allThemes.findIndex(t => t.name === themeName);
            const nextTheme = allThemes[themeIndex === lastThemeIndex ? 0 : themeIndex + 1];
            setTheme({ ...nextTheme.theme });
            setThemeName(nextTheme.name);
        };
    
        return (
            <ThemeContext.Provider
                value={{
                    themeName,
                    setThemeType,
                }}
            >
                <ThemeProvider theme={theme}>{props.children}</ThemeProvider>
            </ThemeContext.Provider>
        );
    };
    
    export default ThemeContext;
    export { ThemeContextProvider };

Но когда я добавляю этот хук useEffect, он перестал работать. Я хочу сохранить выбранную пользователем тему в localStorage и в useEffect загрузить ее обратно. Но она не работает, как показано на изображении с ошибкой

    import React, { createContext, useState, useEffect } from 'react';
    import { ThemeProvider } from '@material-ui/styles';
    import allThemes from './index';
    
    const ThemeContext = createContext({});
    const lastThemeIndex = allThemes.length - 1;
    const ThemeContextProvider = props => {
        const [theme, setTheme] = useState();
        const [themeName, setThemeName] = useState(allThemes[0].name);
    
        useEffect(() => {
            const yourTheme = localStorage.getItem('theme');
            if (yourTheme) {
                const themeIndex = allThemes.findIndex(t => t.name === yourTheme);
                const selectedTheme = allThemes[themeIndex];
                setTheme(selectedTheme);
            } else {
                setTheme(allThemes[0].theme);
            }
        });
    
        const setThemeType = () => {
            const themeIndex = allThemes.findIndex(t => t.name === themeName);
            const nextTheme = allThemes[themeIndex === lastThemeIndex ? 0 : themeIndex + 1];
            setTheme({ ...nextTheme.theme });
            setThemeName(nextTheme.name);
            persistThemeType(nextTheme.name);
        };
    
        function persistThemeType(name) {
            localStorage.setItem('theme', name);
        }
    
        return (
            <ThemeContext.Provider
                value={{
                    themeName,
                    setThemeType,
                }}
            >
                <ThemeProvider theme={theme}>{props.children}</ThemeProvider>
            </ThemeContext.Provider>
        );
    };
    
    export default ThemeContext;
    export { ThemeContextProvider };

введите описание изображения здесь

Это тема:

    import { createMuiTheme } from '@material-ui/core/styles';
    import shadows from './shadows';
    import typography from './typography';
    
    const Caregiver = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#a84632',
                main: '#f16548',
                light: '#f3836c',
            },
            action: {
                active: '#f16548',
            },
        },
        typography,
        shadows,
        overrides: {
            MuiButtonBase: {
                text: {
                    color: 'blue', // Some CSS
                },
            },
        },
    });
    
    const Creator = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#ac6613',
                main: '#f7921c',
                light: '#f8a749',
            },
            action: {
                active: '#f7921c',
            },
        },
        typography,
        shadows,
    });
    
    const Explorer = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#5a5b20',
                main: '#81822e',
                light: '#9a9b57',
            },
            action: {
                active: '#81822e',
            },
        },
        typography,
        shadows,
    });
    
    const Hero = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#004877',
                main: '#0067ab',
                light: '#3385bb',
            },
            action: {
                active: '#0067ab',
            },
        },
        typography,
        shadows,
    });
    
    const Innocent = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#007a9a',
                main: '#00afdd',
                light: '#33bfe3',
            },
            action: {
                active: '#00afdd',
            },
        },
        typography,
        shadows,
    });
    
    const Jester = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#738f27',
                main: '#a5cd39',
                light: '#b7d760',
            },
            action: {
                active: '#a5cd39',
            },
        },
        typography,
        shadows,
    });
    
    const Lover = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#971f48',
                main: '#d92d68',
                light: '#e05786',
            },
            action: {
                active: '#d92d68',
            },
        },
        typography,
        shadows,
    });
    
    const Magician = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#651a63',
                main: '#91268e',
                light: '#a751a4',
            },
            action: {
                active: '#91268e',
            },
        },
        typography,
        shadows,
    });
    
    const Everyperson = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#006369',
                main: '#008e97',
                light: '#33a4ab',
            },
            action: {
                active: '#008e97',
            },
        },
        typography,
        shadows,
    });
    
    const Revolutionary = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#8f1b27',
                main: '#cd2738',
                light: '#d7525f',
            },
            action: {
                active: '#cd2738',
            },
        },
        typography,
        shadows,
    });
    
    const Ruler = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#a18005',
                main: '#e7b708',
                light: '#ebc539',
            },
            action: {
                active: '#e7b708',
            },
        },
        typography,
        shadows,
    });
    
    const Sage = createMuiTheme({
        palette: {
            type: 'dark',
            primary: {
                dark: '#5a331e',
                main: '#81492c',
                light: '#9a6d56',
            },
            action: {
                active: '#81492c',
            },
        },
        typography,
        shadows,
    });
    
    const allThemes = [
        { name: 'Caregiver', theme: Caregiver },
        { name: 'Creator', theme: Creator },
        { name: 'Explorer', theme: Explorer },
        { name: 'Hero', theme: Hero },
        { name: 'Innocent', theme: Innocent },
        { name: 'Jester', theme: Jester },
        { name: 'Lover', theme: Lover },
        { name: 'Magician', theme: Magician },
        { name: 'Everyperson', theme: Everyperson },
        { name: 'Revolutionary', theme: Revolutionary },
        { name: 'Ruler', theme: Ruler },
        { name: 'Sage', theme: Sage },
    ];
    
    export default allThemes;


person Kid    schedule 11.12.2020    source источник
comment
Можете ли вы разместить этот код в codeandbox? Было бы проще определить ошибку!   -  person Prathamesh Koshti    schedule 12.12.2020


Ответы (2)


useState требуется начальное значение для первого рендеринга

    const [theme, setTheme] = useState(allThemes[0].theme);
    
    useEffect(() => {
        const yourTheme = localStorage.getItem('theme');
        if (yourTheme) {
            const themeIndex = allThemes.findIndex(t => t.name === yourTheme);
            const selectedTheme = allThemes[themeIndex];
            setTheme(selectedTheme);
        }
    });

Я удалил блок else useEffect и поместил его значение по умолчанию для theme. В противном случае первый рендер этого компонента будет иметь theme === null.

person Michael Lee    schedule 11.12.2020
comment
Спасибо, я попробовал, но мне все равно нравится TypeError: Cannot read property 'primary' of undefined. Тема не применяется - person Kid; 12.12.2020
comment
Как будто useEffect не влияет - person Kid; 12.12.2020

Просто глупая ошибка вроде:

setTheme(selectedTheme);

должно быть:

setTheme(selectedTheme.theme);
person Kid    schedule 12.12.2020