Есть ли способ с новым 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);
Но есть ли способ экспортировать некоторую функцию с помощью хуков, которые будут иметь состояние и общий профиль с любым компонентом, который хочет получать данные?





обновлено:
Мой предыдущий ответ был - вы можете использовать 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
Нет, это будет ... вы поместите useTodoState () в его собственный файл и импортируете его в любой файл, который вы хотите, и он будет работать с одним состоянием (поэтому я назвал компонент "OneOfTodoViewers")
хм, тогда попробую еще раз: /
Извините, я виноват, и вы правы. Пользовательские хуки не разделяют свое состояние, а только логику. Итак, @ShubhamKhatri ответил правильно
React предоставляет перехватчик useContext для использования Context, который имеет подпись вроде
const context = useContext(Context);
useContextaccepts 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;
так что мне все еще нужно обернуть компонент верхнего уровня в провайдере, чтобы все компоненты обновлялись при изменении данных?
@RTWTMI, да, вам все равно понадобится поставщик на верхнем уровне, useContext является заменой MyComponent.contextTypes = ProfileContext
Сейчас использую вот так.
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>
}
Но это не изменит мои данные задачи в другом компоненте, если я где-то их поменяю :(