我可以用钩子替换上下文吗?
Can I replace context with hooks?
有没有办法用新的反应挂钩 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);
但是有一种方法可以使用钩子导出一些函数,这些函数将具有状态并与任何想要获取数据的组件共享配置文件?
更新:
我之前的回答是 - 您可以为此目的将自定义挂钩与 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.
@ShubhamKhatri 提供了如何使用 useContext() 实现的正确答案
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();
}
然而,就创建一个在不同组件之间共享数据的钩子而言,钩子有一个自己的数据实例,除非你使用上下文,否则不会共享它;
现在我是这样用的
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.log(clickEvent.target)
}, [clickEvent])
return <DivModal show={show}>{children}</DivModal>
}
有没有办法用新的反应挂钩 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);
但是有一种方法可以使用钩子导出一些函数,这些函数将具有状态并与任何想要获取数据的组件共享配置文件?
更新:
我之前的回答是 - 您可以为此目的将自定义挂钩与 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.
@ShubhamKhatri 提供了如何使用 useContext() 实现的正确答案
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();
}
然而,就创建一个在不同组件之间共享数据的钩子而言,钩子有一个自己的数据实例,除非你使用上下文,否则不会共享它;
现在我是这样用的
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.log(clickEvent.target)
}, [clickEvent])
return <DivModal show={show}>{children}</DivModal>
}