Как создать ссылку на дочерний компонент, сохранить его в контексте и передать родному брату в интерфейсе React with Material

#reactjs #typescript #material-ui #scroll-lock

Вопрос:

У меня есть компонент, который выглядит так:

 import React from 'react';
import { Dialog, DialogContent, DialogTitle, Typography } from '@material-ui/core';

const FormDialog = ({ formId, onClose, onSubmit }: Props) => (
  <Dialog open disableBackdropClick>
    <DialogTitle>
      Create New Form
      <br />
      <Typography
        color="textSecondary"
        variant="caption"
      >
        Start a new form by filling in some starter info.
      </Typography>
    </DialogTitle>
    <DialogContent dividers>
      <FormContainer
        formId={formId}
        onSubmit={onSubmit}
        onClose={onClose}
      />
    </DialogContent>
  </Dialog>
);

export default FormDialog;
 

В глубоко вложенном компоненте ниже по строке я хочу заблокировать прокрутку Dialog , когда Popper (с помощью поппера пользовательского интерфейса Material не popper.js) открыта. Я смог сделать это с помощью API vanilla DOM и обнаружил, что компонент, на который мне нужна ссылка, есть DialogContent . (Событие не приближается к ). wheel Dialog

Как мне создать ref указатель DialogContent и отправить его в качестве Context.Provider значения FormContainer ?

Открыт для того, чтобы использовать его в качестве опоры, но предполагаю, что если возможно одно, то возможно и другое?

Я заглянул внутрь forwardRef , и мне кажется, что здесь это не имеет смысла, но машинопись также может обескуражить меня. Я также думал о useRef(null) том, чтобы внутри компонента передать переменный вывод в качестве ref опоры DialogContent , поймать ref.current useEffect его , сохранить useState и передать , FormContainer но не знаю, сработает ли это / надеюсь, что это не решение!

Ответ №1:

Было бы полезно, если бы вы показали, где и как вы реализовали Popper, но я надеюсь, что это даст вам некоторые идеи:

Создайте контекст и заключите FormDialog в него всех детей.

Затем создайте состояние в FormDialog , которое указывает на статус поппера.

Передайте функции состояния и setState туда, где находится Поппер.

ФормДиалог

 const FormDialogContext=createContext(null)

const FormDialog = ({ formId, onClose, onSubmit }: Props) => (

  const [isPopperOpen,setPopperOpen]=useState(false)

  <FormDialogContext.Provider value={[isPopperOpen,setPopperOpen]}>
   <Dialog open disableBackdropClick>
    <DialogTitle>
      Create New Form
      <br />
      <Typography
        color="textSecondary"
        variant="caption"
      >
        Start a new form by filling in some starter info.
      </Typography>
    </DialogTitle>
    <DialogContent dividers>
      <FormContainer
        formId={formId}
        onSubmit={onSubmit}
        onClose={onClose}
      />
    </DialogContent>
  </Dialog>
</FormDialogContext.Provider>
);

export default FormDialog;
 

Теперь в любом компоненте, где находится ваш Поппер

  const [isPopperOpen,setPopperOpen]=useContext(FormDialogContext)

return (<>
         <Button 
          onClick={()=>setPopperOpen(prevState=>!prevState)}>
          Toggle Popper
          </Button>
          <Popper 
          open={isPopperOpen}
         ..................
 

Теперь у вас есть полный контроль над статусом Popper в FormDialog

Комментарии:

1. Спасибо! Так что все наоборот, я хочу управлять FormDialog из Popper , отключив его прокрутку. Я искал решение для этого, которое не включало бы вызов через обратные вызовы, потому что может быть несколько попперов, и я хотел, чтобы функциональность была в крючке.