【问题标题】:open selected modal using reactjs使用 reactjs 打开选定的模式
【发布时间】:2019-09-15 00:21:30
【问题描述】:

我在这个 question 上使用代码共享

代码仅适用于一个模态,我试图添加不止一次,但是当我第一次单击它打开时,所有模态都被触发,然后它可以正常工作,这是我面临的唯一问题

Modal.js

import React, { useRef, useEffect } from "react";
import { createPortal } from "react-dom";

const Modal = ({ isOpen, type, onClose, children }) => {
  const modalEl = useRef(null);
  const handleCoverClick = e => {
    if (e.target.hasAttribute("modal")) {
      onClose();
    }
  };

  useEffect(() => {
    const handleAnimationEnd = event => {
      if (isOpen.type === type && isOpen.modal) {
        if (!isOpen.modal) {
          event.target.classList.remove("show");
          event.target.classList.add("hide");
        } else {
          event.target.classList.remove("hide");
          event.target.classList.add("show");
        }
      }
    };
    modalEl.current.addEventListener("animationend", handleAnimationEnd);

    return () =>
      modalEl.current.removeEventListener("animationend", handleAnimationEnd);
  }, [isOpen]);

  return createPortal(
    <>
      <div
        className={`ModalCover ${isOpen ? "show" : "hide"}`}
        onClick={handleCoverClick}
        modal="true"
      />
      <div
        className={`
            ModalContainer
            ${isOpen.type === type && isOpen.modal ? "slide-up" : "slide-down"}
            ${!modalEl.current && "hide"}
            `}
        ref={modalEl}
      >
        {children}
      </div>
    </>,
    document.body
  );
};

export default Modal;

Style.css

.App {
  font-family: sans-serif;
  text-align: center;
}

.show {
  display: block;
}

.hide {
  display: none;
}

.slide-up {
  transform: translateY(0%);
  animation: slide-up 0.5s forwards;
}

.slide-down {
  transform: translateY(100%);
  animation: slide-down 0.5s forwards;
}

@keyframes slide-up {
  0% {
    transform: translateY(100%);
  }
  100% {
    transform: translateY(0%);
  }
}

@keyframes slide-down {
  0% {
    transform: translateY(0%);
  }
  100% {
    transform: translateY(100%);
  }
}

.ModalCover {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  background-color: rgba(0, 0, 0, 0.15);
}

.ModalContainer {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 400px;
  margin-top: calc(100vh - 400px);
  z-index: 20;
}

Index.js

import React, { useState } from "react";
import ReactDOM from "react-dom";

import Modal from "./Modal";

import "./styles.css";

function App() {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div className="App">
      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
        <div>
          <h3>Coockie</h3>
          <p>content about coockies</p>
          <button
            aria-label="Close this popup"
            onClick={() => setIsOpen({ type: "coockie", modal: false })}
            className="closeBtn"
          >
            x
          </button>
        </div>
      </Modal>

      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
        <div>
          <h3>About us</h3>
          <p>content about us</p>
          <button
            aria-label="Close this popup"
            onClick={() => setIsOpen({ type: "about-us", modal: false })}
            className="closeBtn"
          >
            x
          </button>
        </div>
      </Modal>

      <button onClick={() => setIsOpen({ content: "coockie", modal: true })}>
        coockie modal
      </button>
      <button onClick={() => setIsOpen({ content: "about-us", modal: true })}>
        about us modal
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
  • 实时代码是here

  • 这个link 的代码可以使用一种模式

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    更正:-

    1) 在isOpen 为真之前,我们不想渲染模式

    2) 根据ModalContainer 的标志更正显示和隐藏,而不是在引用中填充当前值,即modalEl.current

    3) 您对两种模式使用相同的状态和更新方法。创建单独的状态,你应该很高兴。目前我有名字isOpen1isOpen2 但你可以给更有意义的名字。

    //index.js

    import React, { useState } from "react";
    import ReactDOM from "react-dom";
    
    import Modal from "./Modal";
    
    import "./styles.css";
    
    function App() {
      const [isOpen1, setIsOpen1] = useState(false);
      const [isOpen2, setIsOpen2] = useState(false);
    
      return (
        <div className="App">
          <>
            {isOpen1 && (
              <Modal isOpen={isOpen1} onClose={() => setIsOpen1(false)}>
                <div>
                  <h3>Coockie</h3>
                  <p>content about coockies</p>
                  <button
                    aria-label="Close this popup"
                    onClick={() => setIsOpen1(false)}
                    className="closeBtn"
                  >
                    x
                  </button>
                </div>
              </Modal>
            )}
          </>
          <>
            {isOpen2 && (
              <Modal isOpen={isOpen2} onClose={() => setIsOpen2(false)}>
                <div>
                  <h3>About us</h3>
                  <p>content about us</p>
                  <button
                    aria-label="Close this popup"
                    onClick={() => setIsOpen2(false)}
                    className="closeBtn"
                  >
                    x
                  </button>
                </div>
              </Modal>
            )}
          </>
    
          <button onClick={() => setIsOpen1(true)}>coockie modal</button>
          <button onClick={() => setIsOpen2(true)}>about us modal</button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    // 模态.js

    import React, { useRef, useEffect } from "react";
    import { createPortal } from "react-dom";
    
    const Modal = ({ isOpen, onClose, children }) => {
      const modalEl = useRef(null);
      const handleCoverClick = e => {
        if (e.target.hasAttribute("modal")) {
          onClose();
        }
      };
    
      useEffect(() => {
        const handleAnimationEnd = event => {
          if (!isOpen) {
            event.target.classList.remove("show");
            event.target.classList.add("hide");
          } else {
            event.target.classList.remove("hide");
            event.target.classList.add("show");
          }
        };
        const modalRef = modalEl.current;
    
        modalEl.current.addEventListener("animationend", handleAnimationEnd);
    
        return () =>
          modalRef.removeEventListener("animationend", handleAnimationEnd);
      }, [isOpen]);
    
      return createPortal(
        <>
          <div
            className={`ModalCover ${isOpen ? "show" : "hide"}`}
            onClick={handleCoverClick}
            modal="true"
          />
          <div
            className={`
              ModalContainer
              ${isOpen ? "slide-up show" : "slide-down hide"}
            `}
            ref={modalEl}
          >
            {children}
          </div>
        </>,
        document.body
      );
    };
    
    export default Modal;
    

    【讨论】:

    • 感谢您的快速回复...我根据您的逻辑更改了代码库,这完全有道理...但仍然触发codesandbox.io/s/rwxm8mk38m ...认为与条件有关Modal.js if (!isOpen) {
    猜你喜欢
    • 2023-03-08
    • 2017-02-09
    • 2014-04-02
    • 2020-12-05
    • 2015-04-14
    • 2017-01-28
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多