【问题标题】:How to implement a use-modal-hook with a alert/confirm/prompt pattern?如何使用警报/确认/提示模式实现使用模式挂钩?
【发布时间】:2021-12-16 07:38:22
【问题描述】:

我已经开始使用ReactModal 向用户显示警告、提示等。 这很好用,但是您必须在您想要显示模式窗口的任何地方添加组件和isOpen 状态和回调。也许我误解了如何正确使用它,但是这种模式很快就会变得乏味。

我想实现一种警报、确认、提示模式,我可以说例如:

const { myAlert, myConfirm } = useModal();

if(myConfirm('Show an alert?')) {
  myAlert('Alert!');
}

以所需的方式显示我的模态。

我的问题在于功能。我希望应用程序在执行以下代码之前等待用户单击模式中的某些内容。现在我的函数在执行后立即返回。

这是我的钩子:

import { useContext } from 'react';
import { ModalContext } from '../App';
import Alert from '../components/Modals/Alert';
import Confirm from '../components/Modals/Confirm';

const useModal2 = () => {
  const { openModal, closeModal } = useContext(ModalContext);

  const alert = (message: string) => {
    openModal(
      <Alert title="Warning" message={message} closeAlert={closeModal} />
    );
  };
  const confirm = (question: string): boolean | undefined => {
    let answer;
    const closeConfirm = (ok: boolean) => {
      answer = ok;
      closeModal();
    };
    openModal(
      <Confirm
        title="Warning"
        question={question}
        closeConfirm={closeConfirm}
      />
    );
    return answer;
  };

  return { alert, confirm };
};

export default useModal2;

这是我的上下文及其值:

interface ModalContextType {
  openModal: (modal: ReactNode) => void;
  closeModal: () => void;
}
export const ModalContext = createContext<ModalContextType>({
  openModal: () => {},
  closeModal: () => {},
});
...
const App = () => {
...
  const [modalContent, setModalContent] = useState<ReactNode>(null);
  const [isModalOpen, { openModal, closeModal }] = useModal();
  const open = (modal: ReactNode) => {
    setModalContent(modal);
    openModal();
  };
  const close = () => {
    setModalContent(null);
    closeModal();
  };
...
return (
  <ModalContext.Provider value={{ openModal: open, closeModal: close }}>
...
        <ReactModal
          className={styles.modalContent}
          overlayClassName={styles.modalOverlay}
          isOpen={isModalOpen}
          onRequestClose={close}
        >
          {modalContent}
        </ReactModal>
    ...

如果我单击以下按钮,onClick 函数只会在我单击确认对话框中的任何内容之前输出 undefined:

      <button
        onClick={() => {
          const answer = confirm('Show an alert?');
          if (answer) {
            alert('The alert you requested!');
          }
          console.log(answer);
        }}
      >
        Confirm!
      </button>

在它检查if 中的值并运行console.log 之前,如何让它在对话框中等待我的回答?有什么想法吗?

这是我在代码框中的代码:https://codesandbox.io/s/blue-architecture-jtjyr

【问题讨论】:

  • 添加了沙盒链接。如果您打开控制台,然后单击确认按钮,您会在单击模式中的任何按钮之前看到它打印“未定义”。我想让它等我点击“确定”或“取消”

标签: javascript reactjs typescript


【解决方案1】:

只需从我的钩子提供的函数中返回一个 Promise。

import { useContext } from 'react';
import { ModalContext } from '../App';
import Alert from '../components/Modals/Alert';
import Confirm from '../components/Modals/Confirm';

const useDialog = () => {
  const { openModal, closeModal } = useContext(ModalContext);

  const alertDialog = (message: string) => {
    return new Promise((resolve) => {
      const closeAlert = () => {
        resolve(true);
        closeModal();
      };

      openModal(
        <Alert title="Warning" message={message} closeAlert={closeAlert} />
      );
    });
  };
  const confirmDialog = (message: string) => {
    return new Promise<boolean>((resolve) => {
      const closeConfirm = (value: boolean) => {
        resolve(value);
        closeModal();
      };

      openModal(
        <Confirm
          title="Warning"
          message={message}
          closeConfirm={closeConfirm}
        />
      );
    });
  };

  return { alertDialog, confirmDialog };
};

export default useModal2;

那么你可以像这样使用它:

      <button
        onClick={() => {
          const answer = await confirmDialog('Show an alert?');
          if (answer) {
            await alertDialog('The alert you requested!');
          }
          console.log('Done showing dialogs for now!');
        }}
      >
        Confirm!
      </button>

在其他地方处理 async/await 可能比您打开对话框的地方更干净。但这是另一个问题。

【讨论】:

  • 非常感谢您花时间帮助我,真的。我可能措辞不佳,但我的问题主要是针对如何使代码执行等待用户响应对话框。我做了一些例子来证明这个问题,忽略了诸如可读性之类的东西。这些示例并不能反映我真实代码库的状态。这就是为什么当你似乎更多地评论无关的问题而不是我问的问题时,我有点生气。
猜你喜欢
  • 1970-01-01
  • 2021-03-18
  • 2019-05-20
  • 2018-01-05
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 2015-10-26
  • 2012-03-10
相关资源
最近更新 更多