useContext 传递了错误的 props

useContext passing wrong props

我的 AppContext.tsx 文件中有我的上下文提供程序

import { useState, useEffect, useContext, createContext } from 'react';

interface AppContextProps {
  children: React.ReactNode
}

const themes = {
  dark: {
    backgroundColor: 'black',
    color: 'white'
  },
  light: {
    backgroundColor: 'white',
    color: 'black'
  }
}

const initialState = {
  dark: false,
  theme: themes.light,
  toggle: () => { console.log('toggle from initalState') }
}

const AppContext = createContext(initialState);

export function AppWrapper({ children }: AppContextProps) {
  const [dark, setDark] = useState(false) // Default theme is light

  // On mount, read the preferred theme from the persistence
  useEffect(() => {
    const isDark = localStorage.getItem('dark') === 'true'
    setDark(isDark)
  }, [dark])

  // To toggle between dark and light modes
  const toggle = () => {
    console.log('toggle from AppWrapper')
    const isDark = !dark
    localStorage.setItem('dark', JSON.stringify(isDark))
    setDark(isDark)
  }

  const theme = dark ? themes.dark : themes.light

  return (
    <AppContext.Provider value={{ theme, dark, toggle }}>
      {children}
    </AppContext.Provider>
  );
}

export function useAppContext() {
  return useContext(AppContext);
}

我将 Appwrapper 插入我的 _app.tsx 文件

import type { ReactElement, ReactNode } from 'react'
import type { NextPage } from 'next'
import type { AppProps } from 'next/app'
import { AppWrapper } from '../contexts/AppContext';
import 'normalize.css/normalize.css';
import '../styles/globals.scss'

type NextPageWithLayout = NextPage & {
  getLayout?: (page: ReactElement) => ReactNode
}

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout
}

const App = ({ Component, pageProps }: AppPropsWithLayout) => {
  const getLayout = Component.getLayout ?? ((page) => page)
  return getLayout(
    <AppWrapper>
      <Component {...pageProps} />
    </AppWrapper>
  )
}

export default App

然后我调用并导入 useAppContext 钩子以在我的 Header 组件中使用它

import styles from './header.module.scss'
import { useAppContext } from '../contexts/AppContext'

const Header = () => {
  const { theme, toggle, dark } = useAppContext()

  return (
    <header className={styles.header}>
      <nav className={styles.nav}>
        <div onClick={toggle} className={styles.switchWrap}>
          <label className={styles.switch}>
            <input type="checkbox" />
            <span className={styles.slider}></span>
          </label>
        </div>
      </nav>
    </header>
  )
}

export default Header

但是,我的 toggle 函数记录 toggle from initalState 而不是 toggle from AppWrapper

下面的代码

const { theme, toggle, dark } = useAppContext()

initialState

获取数据
const initialState = {
  dark: false,
  theme: themes.light,
  toggle: () => { console.log('toggle from initalState') }
}

而不是我传递给下面显示的 value 道具的东西

<AppContext.Provider value={{ theme, dark, toggle }}>
  {children}
</AppContext.Provider>

如何正确地将 value 道具数据而不是来自 initialState 的数据传递到我的组件中?

因为我的应用程序使用的是每页布局,所以我在我的布局文件中插入了 AppWrapper 而不是 _app.tsx 并且一切正常

import Header from './header'
import Footer from './footer'
import { AppWrapper } from '../contexts/AppContext';

interface LayoutProps {
  children: React.ReactNode
}

const Layout = ({ children }: LayoutProps) => {
  return (
    <AppWrapper>
      <Header />
      {children}
      <Footer />
    </AppWrapper>
  )
}

export const getLayout = (page: LayoutProps) => <Layout>{page}</Layout>;

export default Layout