Могу ли я заменить контекст хуками?

Есть ли способ с новым API перехватчиков реакции заменить выборку данных контекста?

Если вам нужно загрузить профиль пользователя и использовать его почти везде, сначала вы создаете контекст и экспортируете его:

export const ProfileContext = React.createContext()

Затем вы импортируете компонент верхнего уровня, загружаете данные и используете поставщика, например:

import { ProfileContext } from 'src/shared/ProfileContext'

<ProfileContext.Provider
      value = {{ profile: profile, reloadProfile: reloadProfile }}
    >
        <Site />
    </ProfileContext.Provider>

Затем в некоторых других компонентах вы импортируете данные профиля следующим образом:

import { ProfileContext } from 'src/shared/ProfileContext'
const context = useContext(profile);

Но есть ли способ экспортировать некоторую функцию с помощью хуков, которые будут иметь состояние и общий профиль с любым компонентом, который хочет получать данные?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
6
0
1 977
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

обновлено:

Мой предыдущий ответ был - вы можете использовать custom-hooks с useState для этой цели, но это было неправильно из-за этого:

Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.

Правильный ответ, как это сделать с помощью useContext (), предоставил @ShubhamKhatri

Но это не изменит мои данные задачи в другом компоненте, если я где-то их поменяю :(

ZiiMakc 04.11.2018 23:15

Нет, это будет ... вы поместите useTodoState () в его собственный файл и импортируете его в любой файл, который вы хотите, и он будет работать с одним состоянием (поэтому я назвал компонент "OneOfTodoViewers")

Melounek 05.11.2018 12:54

хм, тогда попробую еще раз: /

ZiiMakc 05.11.2018 12:57

Извините, я виноват, и вы правы. Пользовательские хуки не разделяют свое состояние, а только логику. Итак, @ShubhamKhatri ответил правильно

Melounek 05.11.2018 13:26
Ответ принят как подходящий

React предоставляет перехватчик useContext для использования Context, который имеет подпись вроде

const context = useContext(Context);

useContext accepts a context object (the value returned from React.createContext) and returns the current context value, as given by the nearest context provider for the given context.

When the provider updates, this Hook will trigger a rerender with the latest context value.

Вы можете использовать его в своем компоненте, например

import { ProfileContext } from 'src/shared/ProfileContext'

const Site = () => {
   const context = useContext(ProfileContext);
   // make use of context values here
}

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

import { ProfileContext } from 'src/shared/ProfileContext'
const useProfileContext = () => {
   const context = useContext(ProfileContext);
   return context;
}

и используйте его в таких компонентах, как

const Site = () => {
   const context = useProfileContext();
}

Однако, что касается создания ловушки, которая обменивается данными между различными компонентами, хуки имеют экземпляр данных для себя и не делятся им, если вы не используете Context;

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

ZiiMakc 04.11.2018 23:34

@RTWTMI, да, вам все равно понадобится поставщик на верхнем уровне, useContext является заменой MyComponent.contextTypes = ProfileContext

Shubham Khatri 05.11.2018 07:46

Сейчас использую вот так.

Contexts.js - экспорт всего контекста из одного места

export { ClickEventContextProvider,ClickEventContext} from '../contexts/ClickEventContext'
export { PopupContextProvider, PopupContext } from '../contexts/PopupContext'
export { ThemeContextProvider, ThemeContext } from '../contexts/ThemeContext'
export { ProfileContextProvider, ProfileContext } from '../contexts/ProfileContext'
export { WindowSizeContextProvider, WindowSizeContext } from '../contexts/WindowSizeContext'

ClickEventContext.js - один из примеров контекста:

import React, { useState, useEffect } from 'react'

export const ClickEventContext = React.createContext(null)
export const ClickEventContextProvider = props => {
  const [clickEvent, clickEventSet] = useState(false)
  const handleClick = e => clickEventSet(e)

  useEffect(() => {
    window.addEventListener('click', handleClick)
    return () => {
      window.removeEventListener('click', handleClick)
    }
  }, [])

  return (
    <ClickEventContext.Provider value = {{ clickEvent }}>
      {props.children}
    </ClickEventContext.Provider>
  )
}

импорт и использование:

import React, { useContext, useEffect } from 'react'
import { ClickEventContext } from 'shared/Contexts'

export function Modal({ show, children }) {
  const { clickEvent } = useContext(ClickEventContext)

  useEffect(() => {
    console.info(clickEvent.target)
  }, [clickEvent])

  return <DivModal show = {show}>{children}</DivModal>
}

Другие вопросы по теме