【问题标题】:React useContext returns default values反应 useContext 返回默认值
【发布时间】:2020-11-23 19:04:55
【问题描述】:

我正在尝试基于https://github.com/luisgserrano/react-dark-mode 创建一个暗模式库(名为 react-goodnight)。

这是创建上下文的地方。

import React from 'react'

const ThemeContext = React.createContext({
  theme: '',
  toggle: () => {}
})

export default ThemeContext

这是我的 useDarkMode 钩子,用于获取/设置主题到 localStorage。

import { useState, useEffect } from 'react'

const useDarkMode = () => {
  const [theme, setTheme] = useState('light')

  const setMode = (mode) => {
    window.localStorage.setItem('theme', mode)
    setTheme(mode)
  }

  const toggle = () => (theme === 'light' ? setMode('dark') : setMode('light'))

  useEffect(() => {
    const localTheme = window.localStorage.getItem('theme')
    localTheme && setTheme(localTheme)
  }, [])

  return [theme, toggle]
}

export default useDarkMode

这是我的图书馆的索引(react-goodnight)。

import React, { useContext } from 'react'
import { ThemeProvider } from 'styled-components'

import { GlobalStyles } from './globalStyles'

import { lightTheme, darkTheme } from './settings'

import ThemeContext from './themeContext'

import useDarkMode from './useDarkMode'

const Provider = ({ children }) => {
  const [theme, toggle] = useDarkMode()

  return (
    <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
      <GlobalStyles />
      <ThemeContext.Provider value={{ theme, toggle }}>
        <button onClick={toggle}>Toggle</button>
        {children}
      </ThemeContext.Provider>
    </ThemeProvider>
  )
}

export const useDarkModeContext = () => useContext(ThemeContext)
export default Provider

最后,这是我尝试使用的示例应用程序。

import React from 'react'

import Provider, { useDarkModeContext } from 'react-goodnight'

const App = () => {
  const { theme, toggle } = useDarkModeContext();

  console.log(theme)
  return (
    <Provider>
      <div>hey</div>
      <button onClick={toggle}>Toggle</button>
    </Provider>
  )
}

export default App

库索引中的“切换”按钮可以正常工作,但我的示例应用程序中的那个按钮不能。 useDarkModeContext() 返回空。

可能是什么问题?

谢谢!

【问题讨论】:

    标签: javascript reactjs react-context


    【解决方案1】:

    你做错了

    第一个选项

    您可以将react-goodnight 提供程序与您的index.js 一起使用并使用useDarkModeContext(),不要将您的index.js 命名为Provider 否则您不能使用来自react-goodnight 的Provider

    import Provider, { useDarkModeContext } from 'react-goodnight'
    
    const Provider = ({ children }) => {
      const [theme, toggle] = useDarkMode()
    
      return (
        <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
          <GlobalStyles />
          <Provider>
            <ThemeContext.Provider value={{ theme, toggle }}>
              <button onClick={toggle}>Toggle</button>
              {children}
            </ThemeContext.Provider>
          </Provider>  
        </ThemeProvider>
      )
    }
    

    第二个选项

    您在index.js 中传递了ThemeContext,因此您也可以在app.js 中访问它

    import React, { useContext } from 'react'
    import ThemeContext from './themeContext'
    
    
    const App = () => {
      const theme = useContext(ThemeContext);
    
      console.log(theme)
      return (
        <Provider>
          <div>hey</div>
          <button onClick={toggle}>Toggle</button>
        </Provider>
      )
    }
    
    export default App
    
    

    【讨论】:

    • 对不起,如果不清楚,但我实际上是在构建 react-goodnight。所以,索引(提供者)是 react-goodnight 的。
    • 哦,我没看到,你能不能让sn-p让我尽快解决它
    • 请制作sn-p,我可以快速解决这个问题,sn-p可以使用codesandbox
    • codesandbox.io/s/stupefied-ganguly-8y7vk?file=/src/app.js,你做了反向方法,从应用程序调用索引,所以你不能重新渲染它
    【解决方案2】:

    它不起作用的原因是因为您在打印 Provider 的同一位置调用 useContext。

    为什么错了?因为 useContext 会寻找 parent 上下文提供者。通过在您调用 useContext 的同一位置呈现 Provider,无需查找父级。您示例中的 useContext 实际上是 App 组件的一部分,该组件不是 Provider 的子。 p>

    您所要做的就是将按钮移到该打印之外,移动到它自己的组件,并且只有 useContext (或者在您的情况下称为 useDarkModeContext 的方法.

    唯一的变化是:

    import React from 'react'
    import Provider, { useDarkModeContext } from 'react-goodnight'
    
    const App = () => {
      return (
        <Provider>
          <div>hey</div>
          <ToggleThemeButton />
        </Provider>
      )
    }
    
    export default App
    
    const ToggleThemeButton = () => {
      const { theme, toggle } = useDarkModeContext();
      return (
        <button onClick={toggle}>Switch Theme outside</button>
      );
    
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-19
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 1970-01-01
      相关资源
      最近更新 更多