Skip to content

Instantly share code, notes, and snippets.

@qkreltms
Last active April 18, 2021 12:17
Show Gist options
  • Select an option

  • Save qkreltms/797644a91d73ecd35ce9da41dfa14393 to your computer and use it in GitHub Desktop.

Select an option

Save qkreltms/797644a91d73ecd35ce9da41dfa14393 to your computer and use it in GitHub Desktop.
interface Factory {
  Component?: any;
  onClosed?: () => void;
  onAfterClosed?: () => void;
  [x: string]: any;
}

export const factory = ({ Component, ...config }: Factory) => {
  const div = document.createElement("div");
  document.body.appendChild(div);
  let currentConfig: Factory = {
    ...config,
    isVisible: true,
    afterClose: () => {
      if (typeof currentConfig.onAfterClose === "function") {
        currentConfig.onAfterClose();
      }
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      destroy(config);
    }
  };

  const destroy = ({ ...config }: Factory) => {
    const unmountResult = ReactDOM.unmountComponentAtNode(div);
    if (unmountResult && div.parentNode) {
      div.parentNode.removeChild(div);
    }

    if (typeof config.onClosed === "function") {
      config.onClosed();
    }

    for (let i = 0; i < destroyFns.length; i += 1) {
      const fn = destroyFns[i];
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      if (fn === close) {
        destroyFns.splice(i, 1);
        break;
      }
    }
  };

  const render = ({ ...config }: Factory) => {
    setTimeout(() => {
      return Component
        ? ReactDOM.render(<Component {...config} />, div)
        : new Error("컴포넌트가 없습니다.");
    });
  };

  const update = (newConfig: Factory) => {
    config = {
      ...currentConfig,
      ...newConfig
    };
    render(config);
  };

  const close = () => {
    const config = {
      ...currentConfig,
      isVisible: false,
      afterClose: () => {
        if (typeof currentConfig.onAfterClose === "function") {
          currentConfig.onAfterClose();
        }
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        destroy(config);
      }
    };
    render(config);
  };

  render(currentConfig);

  destroyFns.push(close);

  return {
    destroy: close,
    update
  };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment