Возможно ли сделать пользовательский хук, возвращающий компонент и функцию управления локальным состоянием компонента

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

Пример логики представлен ниже, однако он абсолютно нерабочий, т.к. useEffect не может отслеживать изменение переменной замыкания.

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

import React, { useEffect, useState } from "react";
import LoginForm from "../LoginForm";
import { Modal } from "antd";

export default () => {

    let isVisible = true;

    const toggleVisibleMode = () => {
        isVisible = !isVisible;
    }

    const LoginModal = () => {

        const [isLoginVisible, setLoginVisible] = useState();

        useEffect(() => {
            setLoginVisible(isVisible);
        }, [isVisible]);

        return (
            <Modal
                centered={true}
                title={'Login'}
                visible={isLoginVisible}
                onCancel={() => setLoginVisible(false)}
                footer={null}
            >
                <LoginForm />
            </Modal>
        );
    }


    return [
        LoginModal,
        toggleVisibleMode
    ];
}

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

Автор решения: Andrew F

Храните состояние, функции и сам компонент модального окна прямо внутри вашего кастомного хука. А из него уже возвращайте все, что необходимо. Обратите внимание, что видимость модалки должна быть привязана к стейту.


export const useModal = () => {
  const [isLoginVisible, setLoginVisible] = useState(false);

  const handleOpen = () => {
    setLoginVisible(true);
  };

  const handleClose = () => {
    setLoginVisible(false);
  };

  const CustomModal = () => {
    return (
      <div>
        <Modal
          centered={true}
          title={"Login"}
          visible={isLoginVisible}
          onCancel={handleClose}
          footer={null}
        >
          <LoginForm />
        </Modal>
      </div>
    );
  };

  return {
    modalComponent: CustomModal,
    modalClose: handleClose,
    modalOpen: handleOpen
  };
};```
→ Ссылка