Antd + react Как запускать модальное окно 'снаружи'?

Во всех примерах что видел Modal запускают по нажатию кнопки, где кнопка находится внутри функции (т.е. составляет с ним единый компонент). Мне надо его вызывать в случае определённого исхода респонса, импортируя как компонент и передавая в него аргумент, который запускает модальное окно (т.е. запуск условно 'снаружи').

Модальное окно.

import React, { useState } from 'react';
import { Modal } from 'antd';


//export default function ModalComponent(mode: boolean) {     // так тоже пробовал
export const ModalComponent = (mode: boolean) => {
    const [isModalOpen, setIsModalOpen] = useState(false);     

    if (mode) {
        setIsModalOpen(true);
    }

    const handleOk = () => {
        setIsModalOpen(false);
    };

    const handleCancel = () => {
        setIsModalOpen(false);
    };

    return (
        <>
            <Modal
                title="Basic Modal"
                closable={{ 'aria-label': 'Custom Close Button' }}
                open={isModalOpen}
                onOk={handleOk}
                onCancel={handleCancel}
            >
                <p>Some contents...</p>
            </Modal>
        </>
    );
};

Вызов нужен тут, в зависимости от, например, response.ok

        .then((response) => {
            if (!response.ok) {
                ModalComponent(true);     // !
            }

Возвращает ошибку Invalid hook call. Hooks can only be called inside of the body of a function component.

Как это починить?


Ответы (1 шт):

Автор решения: Alex Krass

Нельзя использовать хуки вне компонентов, это накладывает ограничения на использование компонентов с ними и принципы работы. Но если вам подойдет, то вы можете сохранять компонент модального окна неактивным и менять его состояние из родительского по результату запроса.

export const Parent = () => {
    const [isOpen, setOpen] = useState(false);

    fetch(...).then((response) => { if (!response.ok) setOpen(true); });
    
    return <>
       ...
       {isOpen && (<ModalComponent mode="isOpen" onClose="(flag) => { setOpen(flag) }" />)}
    </>
}

И вызывая закрытие как обратный вызов в самом компоненте модального окна.

export const ModalComponent = (mode: boolean, onClose: (flag: boolean) => void) => {
    ...
    const handleOk = () => {
        onClose(false);
    };

    const handleCancel = () => {
        onClose(false);
    };
    ...
}
→ Ссылка