在上下文中管理的状态显示未定义



我正在实现一个黑暗的主题来理解 React 上下文。我成功创建了一个将模式保存到本地存储的深色模式,并确定用户是否更喜欢本地存储中的深色模式。 但是现在我想重构以将主题状态保持在上下文中。 我已经在主题上下文中移动了代码,但是我收到错误

错误:TypeError: Cannot read property 'darkMode' of undefined

我似乎无法解决。我的印象是,在这种情况下,我可以使用 useContext 将状态 darkMode 并将 DarkMode 设置到我的应用程序组件中?

import React, { useContext } from 'react';
import ThemeContextProvider, { ThemeContext } from './contexts/ThemeContext';

function App() {
const { darkMode, setDarkMode } = useContext(ThemeContext);
return (
<div className='App'>
<ThemeContextProvider>
<div className={darkMode ? 'dark-mode' : 'light-mode'}>
<nav>
<div className='toggle-container'>
<span style={{ color: darkMode ? 'grey' : 'yellow' }}>☀︎</span>
<span className='toggle'>
<input
checked={darkMode}
onChange={() => setDarkMode((prevMode) => !prevMode)}
type='checkbox'
className='checkbox'
id='checkbox'
/>
<label htmlFor='checkbox' />
</span>
<span style={{ color: darkMode ? '#9c27b0' : 'grey' }}>☽</span>
</div>
</nav>
<main>
<h1>{darkMode ? 'Dark Mode' : 'Light Mode'}</h1>
<h2>Toggle the switch to change theme</h2>
</main>
</div>
</ThemeContextProvider>
</div>
);
}

和主题上下文

import React, { createContext, useState, useEffect } from 'react';
export const ThemeContext = createContext();
const ThemeContextProvider = (props) => {
const [darkMode, setDarkMode] = useState(getInitialMode);
useEffect(() => {
localStorage.setItem('dark', JSON.stringify(darkMode));
getPrefColourScheme();
}, [darkMode]);
function getInitialMode() {
const isReturningUser = 'dark' in localStorage;
const savedMode = JSON.parse(localStorage.getItem('dark'));
const userPrefersDark = getPrefColourScheme();
// if mode was saved -> dark / light
if (isReturningUser) {
return savedMode;
// if preferred colour scheme is dark -> dark
} else if (userPrefersDark) {
return true;
// otherwise -> light
} else {
return false;
}
}
function getPrefColourScheme() {
if (!window.matchMedia) return;
return window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return (
<ThemeContext.Provider value={{ darkMode, setDarkMode }}>
{props.children}
</ThemeContext.Provider>
);
};
export default ThemeContextProvider;

原谅我的无知,我正在努力解决这个问题。 任何帮助将不胜感激。

我认为您只能使用

const { darkMode, setDarkMode } = useContext(ThemeContext);

每当使用此钩子的组件上方的某些组件具有<Context.Provider>

但是,您在App组件中使用此挂钩 - 它不是提供程序的子级。

您可以做的是将子组件分离到一个新组件并在那里使用钩子,或者将您的<App />渲染为<ThemeContextProvider>的子组件(这意味着将您的<ThemeContextProvider>移动到另一个位置(

选项 1

const FooComp = () => {
const { darkMode, setDarkMode } = useContext(ThemeContext);
return (
<div className={darkMode ? 'dark-mode' : 'light-mode'}>
<nav>
<div className='toggle-container'>
<span style={{ color: darkMode ? 'grey' : 'yellow' }}>☀︎</span>
<span className='toggle'>
<input
checked={darkMode}
onChange={() => setDarkMode((prevMode) => !prevMode)}
type='checkbox'
className='checkbox'
id='checkbox'
/>
<label htmlFor='checkbox' />
</span>
<span style={{ color: darkMode ? '#9c27b0' : 'grey' }}>☽</span>
</div>
</nav>
<main>
<h1>{darkMode ? 'Dark Mode' : 'Light Mode'}</h1>
<h2>Toggle the switch to change theme</h2>
</main>
</div>
)
}

然后在App

function App() {
return (
<div className='App'>
<ThemeContextProvider><FooComp /></ThemeContextProvider>
)
}

选项 2

在你渲染的地方App你做

<ThemeContextProvider><App /></ThemeContextProvider>

然后您从App中删除ThemeContextProvider

如果您正在使用类组件并遇到此问题 上下文存储在类组件中称为上下文的变量中

import React, {Component, useContext} from 'react';
import {ThemeContext} from '../contexts/ThemeContext';

class Navbar extends Component {
static contextType = ThemeContext
render() {
console.log(this.context); 
return ( 
<nav>
<h1>Content Apps</h1>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
);
}
}
export default Navbar;

相关内容

  • 没有找到相关文章