Рефакторинг вашего компонента контекста и устранение запутанного доступа к данным

В реакции мы передаем данные/функции от родителя к дочернему. Таким образом, если у родителя есть какие-то данные/функция, которые нужны дочернему элементу на каком-то глубоком уровне, мы должны передать его в качестве реквизита через каждый компонент на пути от родителя к предполагаемому дочернему элементу. Используйте встроенный в реакцию хук useContext, чтобы решить эту проблему.

Хук React useContext() помогает легко передавать данные любым дочерним элементам на любой глубине. По сути, есть 2 шага —

  1. Создайте Provider, передайте значения, к которым вы хотите получить доступ,и оберните ими родительский компонент.
  2. Используйте хук useContext() для доступа к переданным значениям дочернего элемента на любой глубине родителя.

Умный способ — реорганизовать коды, связанные с контекстом, в отдельную папку context, которая содержит все контексты, используемые в приложении. В каждом компоненте внутри папки context создайте контекст (можно также экспортировать настраиваемый хук для доступа к данным) и экспортируйте поставщика. Вот как должен выглядеть пример ThemeProvider (context/ThemeContext.js):

import { createContext, useContext } from 'react'

const ThemeContext = createContext()

export const useTheme = () => useContext(ThemeContext)

export default function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('dark')

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

Теперь предположим, что мы хотим, чтобы все дочерние элементы компонента _app использовали эту тему и setTheme. Итак, наш родительский компонент — это _app, там —

import ThemeProvider from 'context/ThemeContext'

export default function App() {
  return (
    <ThemeProvider>
      // child components here
    </ThemeProvider>
  )
}

И в любом дочернем компоненте на любой глубине, когда мы хотим использовать либо theme, либо setTheme, мы можем просто использовать хук useTheme(), например —

import { useTheme } from 'context/ThemeContext'

export default function ChildComponentXY() {
  const { theme, setTheme } = useTheme()

  // ... rest of the component codes
}

Таким образом, мы можем иметь несколько провайдеров контекста внутри приложения, все они рефакторинг и разделены на красивую папку с именем context.