Использование хука useContext в React

Иногда при создании приложения на React бывает сложно передавать реквизиты от одного компонента к другому без сверления реквизитов. Одним из встроенных инструментов React для решения этой проблемы является хук useContext.

Контекст React позволяет вам обернуть ваши компоненты в провайдера контекста. Значения, которые вам нужно передавать компонентам, могут быть инициализированы на верхнем уровне, а затем доступны в любом компоненте с помощью хука useContext.

Давайте рассмотрим простой пример.

Допустим, у нас есть приложение, которое содержит два компонента: один — это текстовый ввод, а другой — компонент, который будет отображать значение, введенное пользователем.

Вот структура файла.

К сожалению, мы не можем просто передать вводимое значение между братьями и сестрами Input и Result. В действительности, в этом очень простом примере лучшим способом решения проблемы было бы поднять состояние в компонент App, а затем передать его вниз в каждый из дочерних компонентов. Но допустим, вы создаете более сложное приложение, и вам нужно передать состояние на несколько уровней вниз по дереву компонентов, избегая при этом prop drilling — вот тут-то и приходит на помощь Context.

Стартовые файлы для этого примера можно найти здесь.

Сначала мы хотим создать новый файл и создать наш контекст с помощью React.createContext.

import * as React from "react"

export type InputValues = {
  nameValue: string
  setNameValue: React.Dispatch<React.SetStateAction<string>>
}

export const InputContext = React.createContext<InputValues>({
  nameValue: "",
  setNameValue: () => console.info("Name not yet initialised"),
})
Вход в полноэкранный режим Выйти из полноэкранного режима

В объекте createContext вам нужно будет добавить и инициализировать все необходимые значения. Здесь мы установили nameValue, которое будет использоваться в компоненте Result для отображения имени, и setNameValue, которое будет использоваться для установки значения в компоненте Input.

Далее мы создадим собственный хук, который позже сможем использовать в провайдере.

import * as React from "react"

import { InputValues } from "./input-context"

export function useInputProvider(): InputValues {
  const [nameValue, setNameValue] = React.useState("")

  return {
    nameValue,
    setNameValue,
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Здесь мы просто устанавливаем nameValue и setNameValue с помощью хука React useState и возвращаем их для использования в нашем следующем шаге.

Теперь нам нужно перейти в наш файл App и обернуть наши компоненты Input и Result в контекстный провайдер.

import { Input, Result } from "./components"

import { InputContext } from "./context"
import { useInputProvider } from "./context/use-input-provider"

function App() {
  const nameValue = useInputProvider()

  return (
    <div className="inputForm">
      <InputContext.Provider value={nameValue}>
        <Input />
        <Result />
      </InputContext.Provider>
    </div>
  )
}

export default App
Вход в полноэкранный режим Выйти из полноэкранного режима

Итак, мы используем InputContext, который мы создали в первом шаге, и обернем дочерние компоненты в провайдер. Затем мы можем использовать хук useInputProvider, который мы установили во втором шаге, чтобы передать nameValue и setNameValue в качестве значения провайдера.

Теперь, когда мы настроили провайдера, как нам получить доступ к значениям в наших дочерних компонентах?

Сначала перейдем к нашему компоненту Input.

import * as React from "react"
import { InputContext } from "../context"

export function Input(): JSX.Element {
  const { setNameValue } = React.useContext(InputContext)

  function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    setNameValue(e.target.value)
  }

  return (
    <form>
      <label htmlFor="name">Name: </label>
      <input type="text" id="name" name="name" onChange={handleChange} />
    </form>
  )
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Здесь нам нужно получить доступ к setNameValue, чтобы установить значение имени на то, которое пользователь введет в поле ввода. Для этого мы можем использовать хук useContext и передать наш InputContext. Затем вы можете извлечь setNameValue вот так —

const { setNameValue } = React.useContext(InputContext)
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем вы можете продолжить и использовать setNameValue, чтобы принять входное значение.

Наконец, давайте перейдем к компоненту Result и получим доступ к nameValue таким же образом, используя useContext.

import * as React from "react"
import { InputContext } from "../context"

export function Result() {
  const { nameValue } = React.useContext(InputContext)
  return <div>{nameValue}</div>
}
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы можем передать nameValue в <div> для отображения результата.

Вот и все! Вы можете найти готовый код здесь.

Оцените статью
devanswers.ru
Добавить комментарий