M M*_*ler 5 javascript reactjs react-context
假设我想为“手风琴”(一组可折叠面板)创建一个 UI 组件。父组件控制哪些面板打开的状态,而子面板应该能够读取上下文以确定它们是否打开。
const Accordion = ({ children }) => {
const [openSections, setOpenSections] = useState({})
const isOpen = sectionId => Boolean(openSections[sectionId])
const onToggle = sectionId => () =>
setOpenSections({ ...openSections, [sectionId]: !openSections[sectionId] })
const context = useMemo(() => createContext(), [])
// Can't tell children to use *this* context
return (
<context.Provider value={useMemo(() => ({ isOpen, onToggle }), [isOpen, onToggle])}>
{children}
</context.Provider>
)
}
const AccordionSection = ({ sectionId, title, children }) => {
const { isOpen, onToggle } = useContext(context)
// No way to infer the right context
return (
<>
<button onClick={onToggle(sectionId)}>{isOpen(sectionId) ? 'Close' : 'Open'}</button>
{isOpen && children}
</>
)
}
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一方法是在Accordion每次children更改时运行效果,然后children深入遍历并查找AccordionSection组件,同时不递归任何嵌套Accordion组件 - 然后作为 propcloneElement()注入context每个AccordionSection.
这似乎不仅效率低下,而且我什至不完全确定它会起作用。这取决于children效果运行时是否完全水合,我不确定是否会发生这种情况,并且还需要Accordion在深子级发生变化时调用 's 的渲染器,我也不确定。
我目前的方法是为实现手风琴的开发人员创建一个自定义挂钩。钩子返回一个函数,该函数返回isOpen和onToggle必须手动传递给每个渲染的函数AccordionSection。它有效并且可能比 children 解决方案更优雅,但需要更多的开销,因为开发人员需要使用钩子来维护否则将被封装在Accordion.
React.createContext将返回一个包含 2 个组件的对象:
这两个组件可以共享数据,可以从树上Consumer最近的位置“抓取”上下文数据(或使用钩子而不是渲染)。ProvideruseContextConsumer
您应该在父组件外部创建上下文对象,并使用它来渲染组件Consumer内部children(或使用useContext钩子)。
简单的例子:
const myContext = createContext();
const Accordion = ({ children }) => {
// ...
return (
<myContext.Provider value={...} >
{children}
</myContext.Provider>
)
}
const AccordionSection = (...) => {
const contextData = useContext(myContext);
// use the data of your context as you wish
// ...
}
Run Code Online (Sandbox Code Playgroud)
请注意,我使用了useContext挂钩而不是渲染Consumer,这取决于您是否想使用该挂钩或Consumer.
您可以查看更多示例并从文档中获取更多详细信息
| 归档时间: |
|
| 查看次数: |
635 次 |
| 最近记录: |