Falta pouco!

0 dias

0 horas

0 min

0 seg

Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Sobre o ModalComment

Ola, gostaria de entender sobre o .current.openModal, vi que por dentro dos componente ele se referencia a um dialog, o que deu a entender que esse componente oferece o método showModal e close, mas como eu poderia fazer o mesmo para um componente criado por mim. Achei super util.

1 resposta
solução!

Oi, Everton! Como vai?

Vamos resolver isso. Para ter um .current.openModal igual ao que você viu, exponha métodos do componente filho para o pai usando forwardRef + useImperativeHandle. Assim, o pai chama ref.current.openModal() ou ref.current.closeModal() mesmo que o filho encapsule um <dialog> (que tem showModal/close) ou até se for outro container controlado por estado.

Por exemplo:

  1. Modal que usa <dialog> e expõe openModal/closeModal
  2. Uso no componente pai chamando ref.current.openModal()

-- Modal.tsx --

import React, { forwardRef, useImperativeHandle, useRef } from 'react';

type ModalHandle = {
  openModal: () =&gt; void;
  closeModal: () =&gt; void;
};

export const Modal = forwardRef&lt;ModalHandle, { title?: string }&gt;(
  ({ title = 'Titulo' }, ref) =&gt; {
    const dialogRef = useRef&lt;HTMLDialogElement | null&gt;(null);

    useImperativeHandle(ref, () =&gt; ({
      openModal() {
        if (dialogRef.current?.showModal) dialogRef.current.showModal();
      },
      closeModal() {
        if (dialogRef.current?.close) dialogRef.current.close();
      },
    }));

    return (
      &lt;dialog ref={dialogRef}&gt;
        &lt;h2&gt;{title}&lt;/h2&gt;
        &lt;p&gt;Conteudo do modal&lt;/p&gt;
        &lt;button onClick={() =&gt; ref &amp;&amp; (dialogRef.current?.close?.())}&gt;Fechar&lt;/button&gt;
      &lt;/dialog&gt;
    );
  }
);

-- Parent.tsx --

import React, { useRef } from 'react';
import { Modal } from './Modal';

export default function Parent() {
  const modalRef = useRef&lt;{ openModal: () =&gt; void; closeModal: () =&gt; void } | null&gt;(null);

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; modalRef.current?.openModal()}&gt;Abrir modal&lt;/button&gt;
      &lt;button onClick={() =&gt; modalRef.current?.closeModal()}&gt;Fechar modal&lt;/button&gt;

      &lt;Modal ref={modalRef} title="Exemplo" /&gt;
    &lt;/div&gt;
  );
}

Por que funciona?

  • forwardRef: permite ao pai passar ref para o filho.
  • useImperativeHandle(ref, factory): define quais métodos ficam visíveis no ref.current.
  • Se seu componente não usa <dialog>, exponha métodos que alteram state interno (ex.: setIsOpen(true/false)) e renderize/oculte o modal via JSX/CSS.

Alternativa sem <dialog> (controlado por estado):

-- ModalControlled.tsx --

import React, { useState, forwardRef, useImperativeHandle } from 'react';

type ModalCtrlHandle = { openModal: () =&gt; void; closeModal: () =&gt; void; };

export const ModalControlled = forwardRef&lt;ModalCtrlHandle, {}&gt;((_, ref) =&gt; {
  const [isOpen, setIsOpen] = useState(false);

  useImperativeHandle(ref, () =&gt; ({
    openModal() { setIsOpen(true); },
    closeModal() { setIsOpen(false); },
  }));

  if (!isOpen) return null;

  return (
    &lt;div role="dialog" aria-modal="true" style={{ inset: 0, position: 'fixed' }}&gt;
      &lt;div&gt;Conteudo&lt;/div&gt;
      &lt;button onClick={() =&gt; setIsOpen(false)}&gt;Fechar&lt;/button&gt;
    &lt;/div&gt;
  );
});
  • Exponha métodos com useImperativeHandle.
  • Encapsule o detalhe interno (dialog.showModal/close ou state).
  • Use o método a partir do pai via ref.current.openModal().

Espero ter ajudado. Conte com o apoio do Fórum na sua jornada. Fico à disposição.

Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado