我正在实现一个黑暗的主题来理解 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;