簡體   English   中英

有什么實用的方法可以在組件中調用 `React.createContext()` 嗎?

[英]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}
    </>
  )
}

我能想到的唯一方法是讓Accordionchildren發生變化時運行效果,然后深入遍歷children並找到AccordionSection組件,同時不遞歸任何嵌套的Accordion組件——然后cloneElement()並注入context作為道具每個AccordionSection

這似乎不僅效率低下,而且我什至不完全確定它會起作用。 這取決於效果運行時children是否完全水合,我不確定是否會發生這種情況,並且它還要求Accordion的渲染器在深度孩子發生變化時被調用,我也不確定。

我目前的方法是為實現手風琴的開發人員創建一個自定義掛鈎。 該鈎子返回一個函數,該isOpen返回必須手動傳遞給每個渲染的AccordionSectionisOpenonToggle函數。 它有效並且可能比 children 解決方案更優雅,但需要更多的開銷,因為開發人員需要使用鈎子來維護原本封裝在Accordion狀態。

React.createContext將返回一個包含 2 個組件的對象:

  1. 提供者
  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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM