Есть ли практический способ вызова `React.createContext ()` внутри компонента? - PullRequest
1 голос
/ 30 января 2020

Допустим, я хочу создать 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 и onToggle, которые должны быть вручную переданы каждому отображаемому AccordionSection. Он работает и, возможно, более элегантен, чем дочернее решение, но требует больше накладных расходов, поскольку разработчику необходимо использовать ловушку только для того, чтобы поддерживать то, что в ином случае было бы инкапсулировано в Accordion.

1 Ответ

2 голосов
/ 30 января 2020

React.createContext вернет объект, который содержит 2 компонента:

  1. Поставщик
  2. Потребитель

Эти 2 компонента могут совместно использовать данные, Consumer может "захватить" данные контекста из ближайшего Provider вверх по дереву (или использовать хук useContext вместо рендеринга Consumer).

Вы должны создать объект контекста вне родительского компонента и используйте его для визуализации Consumer внутри ваших children компонентов (или используйте useContext hook).

Простой пример:

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
  // ...
}

Обратите внимание, что я использовал * Хук 1024 * useContext вместо рендеринга Consumer, вам решать, хотите ли вы использовать хук или Consumer.

. Вы можете увидеть больше примеров и получить больше деталей от * документы 1031 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...