useModal 후크를 통해 React에서 모달 대화 상자 사용. 가능한 한 간단합니다.

모달 대화 상자를 통해 사용자와 상호 작용하는 가장 쉬운 방법은 window.alert , window.confirm , window.prompt 와 같은 브라우저 API를 사용하는 것입니다. 단 하나의 문제가 있습니다. 모양을 사용자 지정할 수 없습니다.

<body>
  <div>
    <button class="trigger">I want to drink something!</button>
    <div class="result"></div>
  </div>
  <script>
    const resultElement = document.querySelector(".result");
    const setDrink = (drink) => {
      if (drink) {
        resultElement.innerText = `Enjoy your drink, ${drink}`;
      } else {
        resultElement.innerText = ``;
      }
    };

    document.querySelector(".trigger").addEventListener("click", () => {
      setDrink(null);

      const coffee = window.confirm("Do you like coffee?");
      if (coffee) return setDrink("Coffee");

      const tea = window.confirm("Do you like tea?");
      if (tea) return setDrink("Tea");

      setDrink("Tequila");
    });
  </script>
</body>


(거의) 같은 방식으로 React를 사용한다고 상상해 봅시다.

const OrderDrink = () => {
  const [drink, setDrink] = useState();
  const modal = useModal();

  return (
    <div>
      <button
        onClick={async () => {
          setDrink(null);

          const coffee = await modal.open("Do you like coffee?");
          if (coffee) return setDrink("Coffee");

          const tea = await modal.open("Do you like tea?");
          if (tea) return setDrink("Tea");

          return setDrink("Tequila");
        }}
      >
        I want to drink something!
      </button>
      <div>{drink && `${drink} is your drink!`}</div>
      <ConfirmModal {...modal} />
    </div>
  );
}


좋아 보인다, 그렇지 않니? 마법은 useModal 후크 내부에서 발생합니다. Promise 함수 안에 open를 생성하기만 하면 됩니다. 그리고 사용자 상호 작용의 결과(페이로드)로 close 함수 내에서 해결합니다.

const useModal = (initial = {}) => {
  const state = useMemo(() => ({ resolve: null, data: initial.data }), []);
  const [opened, setOpened] = useState(initial.opened);

  const open = useCallback((data) => {
    setOpened(true);
    state.data = data;
    return new Promise((resolve) => { state.resolve = resolve; });
  }, []);

  const close = useCallback((payload) => {
    setOpened(false);
    state.resolve(payload);
  }, []);

  return { opened, data: state.data, close, open };
};


그리고 한 단계 더 - 모달 대화 구성 요소:

const ConfirmModal = (props) => {
  if (!props.opened) {
    return null;
  }

  return (
    <aside>
      <div>
        {props.data}
        <br />
        <button onClick={() => props.close(true)}>yes</button>
        <button onClick={() => props.close(false)}>no</button>
      </div>
    </aside>
  );
};

AlertModal , ConfirmModal , PromptModal 와 같은 재사용 가능한 대화 세트를 만들 수 있습니다. 그리고 특정 사용 사례에 따라 EditProductModal 와 같은 도메인별 논리가 있는 대화 상자가 될 수 있습니다.

출처: https://gist.github.com/dsvgit/2f0a34201d1b075fdd42d2a79d5c5fc8
샌드박스: https://codesandbox.io/s/use-modal-hook-5nnr1v

좋은 웹페이지 즐겨찾기