[英]Is there any practical way to call `React.createContext()` within a component?
假設我想為“手風琴”(一組可折疊面板)創建一個 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}
</>
)
}
我能想到的唯一方法是讓Accordion
在children
發生變化時運行效果,然后深入遍歷children
並找到AccordionSection
組件,同時不遞歸任何嵌套的Accordion
組件——然后cloneElement()
並注入context
作為道具每個AccordionSection
。
這似乎不僅效率低下,而且我什至不完全確定它會起作用。 這取決於效果運行時children
是否完全水合,我不確定是否會發生這種情況,並且它還要求Accordion
的渲染器在深度孩子發生變化時被調用,我也不確定。
我目前的方法是為實現手風琴的開發人員創建一個自定義掛鈎。 該鈎子返回一個函數,該isOpen
返回必須手動傳遞給每個渲染的AccordionSection
的isOpen
和onToggle
函數。 它有效並且可能比 children 解決方案更優雅,但需要更多的開銷,因為開發人員需要使用鈎子來維護原本封裝在Accordion
狀態。
React.createContext
將返回一個包含 2 個組件的對象:
這兩個組件可以共享數據, Consumer
可以從最近的Provider
“抓取”樹上的上下文數據(或使用useContext
鈎子而不是呈現Consumer
)。
您應該在父組件外部創建上下文對象,並使用它在children
組件內部呈現Consumer
(或使用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
// ...
}
請注意,我用的useContext ,而不是渲染鈎Consumer
,它取決於你,如果你想使用掛鈎,或Consumer
。
您可以查看更多示例並從文檔中獲取更多詳細信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.