Eu tenho um componente DialogueWindow geral:
function DialogueWindow({elements}) {
return (
<div className="backdrop">
<dialog className="dialogue-window">
{elements}
</dialog>
</div>
)
}
export default DialogueWindow
Ele exibe dentro dele todos os elementos aos quais é passado. Atualmente, estou passando um elemento FileUploader, que tem um botão de cancelar para o usuário fechar a caixa de diálogo.
Em App.js:
<DialogueWindow
elements={
<FileUploader/>
}
/>
No FileUploader:
function FileUploader() {
...
return (
<div className="file-uploader">
...
<div className="file-uploader-button-container">
<button>
Upload
</button>
<button>
Cancel
</button>
</div>
</div>
)
}
export default FileUploader
Percebi que em JavaScript padrão você chama document.getElementById() para buscar o elemento de diálogo e, em seguida, chama o método close() nele. Mas como isso funciona em React?
Basicamente, no React, o estado geralmente está vinculado ao componente que precisa controlar a renderização. Então, no seu caso, o
DialogueWindow
é o controle. Isso não decide se o diálogo está aberto ou fechado; isso provavelmente depende do upstream (comoapp
), e é por isso que seu método não funcionará.Qualquer componente filho (
FileUploader
) pode instruir seu componente pai (DialogueWindow
) ou avô (App
) a fazer algo como fechar o diálogo, passando uma função de retorno de chamada como prop . O filho então chama essa função quando o botão é clicado.Como consertar:
Adicione uma variável de estado a
app
(ou algo equivalente). Isso rastreará se o diálogo está aberto.App
deve passar o estado e uma função para fechar o diálogo paraDialogueWindow
.DialogueWindow
precisa passar a função close paraFileUploader
.FileUploader
O botão cancelar precisa chamar a função fechar acima.Em App.js (ou equivalente): você precisa adicionar a variável de estado no seu aplicativo e mostrar o diálogo condicionalmente.
Em DialougeWindow.js : Pegue um prop onClose e obtenha uma referência direta ao DOM
<dialouge>
Em FileUploader.js : agora ele aceita a propriedade onClose de seu pai.
O que acontece:
Em
App
, isDialogueOpen é falso.DialogueWindow
não é renderizado.O usuário clica no botão abrir no
App
.handleOpenDialogue no aplicativo é chamado, definindo isDialogueOpen como true.
O React renderiza novamente o aplicativo. Como isDialogueOpen é verdadeiro,
DialogueWindow
agora ele é renderizado.App
passa handleCloseDialogue como onClose paraDialogueWindow
e também paraFileUploader
dentroDialogueWindow
da propriedade elements de 's.DialogueWindow
montagens. Seu useEffect é executado, chamando dialogRef.current.showModal(), o que significa que a caixa de diálogo nativa agora está visível. Em seguida, ele adiciona o ouvinte de evento nativo close para que possamos modificá-lo posteriormente.O FileUploader é montado dentro do
DialogueWindow
. Ele recebe handleCloseDialogue como sua propriedade onClose.O usuário clica no botão "Cancelar" no FileUploader.
handleCancelClick no FileUploader é chamado, o que executa props.onClose().
handleCloseDialogue no aplicativo é chamado, definindo isDialogueOpen novamente como falso.
O React renderiza novamente o aplicativo. Como isDialogueOpen é falso, a renderização condicional isDialogueOpen && (...) é falsa e
DialogueWindow
é removida do DOM.Ao
DialogueWindow
desmontar, o React limpa o useEffect, removendo o ouvinte nativo do evento close. O elemento nativo dialog também é removido do DOM.Faz sentido?
Você pode ler mais sobre estado e adereços em React Learn: Gerenciando estado e React Learn: Escotilhas de escape
A maneira típica de fazer isso é adicionando uma variável de estado que determina se
<DialogueWindow />
ele será renderizado ou não.A variável de estado será controlada por meio de uma função, que precisa ser passada do pai para onde o
Cancel
botão está.Também pode ser necessário chamar
onClose
após um Upload bem-sucedido para evitar que a caixa de diálogo fique visível para sempre.Aplicativo.js:
FileUploader.js: