Reactjs 为什么React.createPortal不';t处理事件。停止播放?

Reactjs 为什么React.createPortal不';t处理事件。停止播放?,reactjs,Reactjs,我正在使用React.createPortal对自定义模式进行试验,如果我只是通过模式内的按钮打开和关闭模式,并且默认结果显示在下面的组件上,那么一切都正常,但我想要实现的是,当我单击模式容器(暗覆盖div)时,它应该关闭模式,因此,我在它上面添加了一个exithandler,但问题是,即使exithandler中有event.stopperPagation()函数,模式内容中的默认表单按钮行为也不再起作用 下面是两个模态的codesandbox示例,一个有表单,一个没有表单: 模态容器: im

我正在使用React.createPortal对自定义模式进行试验,如果我只是通过模式内的按钮打开和关闭模式,并且默认结果显示在下面的组件上,那么一切都正常,但我想要实现的是,当我单击模式容器(暗覆盖div)时,它应该关闭模式,因此,我在它上面添加了一个exithandler,但问题是,即使exithandler中有event.stopperPagation()函数,模式内容中的默认表单按钮行为也不再起作用

下面是两个模态的codesandbox示例,一个有表单,一个没有表单:

模态容器:

import React from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal-root");

function Modal({ exitHandler, children }) {
  return createPortal(
    <div className="modal" onClick={exitHandler}>
      {children}
    </div>,
    modalRoot
  );
}

export default Modal;
import React from "react";

const HelloWorld = ({ user, onClose }) => {
  
  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Greetings</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <p>{user ? `Hello ${user}!` : "Greetings!"}</p>
      </div>
    </div>
  );
};

export default HelloWorld;
import React, { forwardRef, useEffect } from "react";

const SignUp = forwardRef((props, ref) => {
  const { onClose, onSignUp, handleChange, inputError, user } = props;

  useEffect(() => {
    ref.current.focus();
  });

  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Sign Up</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <form onSubmit={onSignUp} className="modal-form">
          <label className="input-label">
            <span>Name:</span>
            <input
              type="text"
              onChange={handleChange}
              value={user}
              ref={ref}
              className={inputError === true ? "input-error" : null}
            />
          </label>
          <input className="btn" type="submit" value="Submit" />
        </form>
      </div>
    </div>
  );
});

export default SignUp;
const App = () => {
  const [modalState, setModalState] = useState(false);
  const [modalId, setModalId] = useState(null);
  const [inputError, setInputError] = useState(false);
  const [user, setUser] = useState("");
  const [userStatus, setUserStatus] = useState("");

  const nameRef = useRef(null);

  const handleShowModal = (e) => {
    const modalId = e.target.id.toString();
    return [setModalState(true), setModalId(modalId)];
  };

  const handleHideModal = (event) => {
    event.stopPropagation(); // This doesn't work
    setModalState(false);
  };

  const runSignUpResult = useCallback(() => {
    handleHideModal();
    setUserStatus(`Thank you ${user} for signing up!`);
  }, [user]);

  const handleValidation = useCallback(
    (nameParameter) => {
      if (nameParameter.length === 0) {
        nameRef.current.focus();
        setInputError(true);
      } else {
        return [setInputError(false), runSignUpResult()];
      }
    },
    [runSignUpResult]
  );

  const handleSignUp = useCallback(
    (e) => {
      e.preventDefault();
      const name = nameRef.current.value;
      handleValidation(name);
    },
    [nameRef, handleValidation]
  );

  const handleChange = (e) => {
    setUser(e.target.value);
  };

  const modal = modalState ? (
    <Modal exitHandler={handleHideModal}>
      {modalId === "greeting" ? (
        <HelloWorld onClose={handleHideModal} user={user} />
      ) : (
        <SignUp
          onClose={handleHideModal}
          onSignUp={handleSignUp}
          handleChange={handleChange}
          user={user}
          ref={nameRef}
          inputError={inputError}
          modalId={modalId}
        />
      )}
    </Modal>
  ) : null;

  return (
    <div className="App">
      <AppHeader />

      <main className="app-body">
        <section className="modal-btns">
          <button id="greeting" className="btn" onClick={handleShowModal}>
            Greetings!
          </button>
          <button id="signup" className="btn" onClick={handleShowModal}>
            Sign Up
          </button>
        </section>
        <section>{modal}</section>
        <section className="user-status">
          <h3>{user.length === 0 ? null : userStatus}</h3>
        </section>
      </main>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
从“React”导入React;
从“react dom”导入{createPortal};
const modalRoot=document.getElementById(“模态根”);
函数模态({exitHandler,children}){
返回createPortal(
{儿童}
,
莫代尔根
);
}
导出默认模式;
模态内容1:

import React from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal-root");

function Modal({ exitHandler, children }) {
  return createPortal(
    <div className="modal" onClick={exitHandler}>
      {children}
    </div>,
    modalRoot
  );
}

export default Modal;
import React from "react";

const HelloWorld = ({ user, onClose }) => {
  
  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Greetings</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <p>{user ? `Hello ${user}!` : "Greetings!"}</p>
      </div>
    </div>
  );
};

export default HelloWorld;
import React, { forwardRef, useEffect } from "react";

const SignUp = forwardRef((props, ref) => {
  const { onClose, onSignUp, handleChange, inputError, user } = props;

  useEffect(() => {
    ref.current.focus();
  });

  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Sign Up</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <form onSubmit={onSignUp} className="modal-form">
          <label className="input-label">
            <span>Name:</span>
            <input
              type="text"
              onChange={handleChange}
              value={user}
              ref={ref}
              className={inputError === true ? "input-error" : null}
            />
          </label>
          <input className="btn" type="submit" value="Submit" />
        </form>
      </div>
    </div>
  );
});

export default SignUp;
const App = () => {
  const [modalState, setModalState] = useState(false);
  const [modalId, setModalId] = useState(null);
  const [inputError, setInputError] = useState(false);
  const [user, setUser] = useState("");
  const [userStatus, setUserStatus] = useState("");

  const nameRef = useRef(null);

  const handleShowModal = (e) => {
    const modalId = e.target.id.toString();
    return [setModalState(true), setModalId(modalId)];
  };

  const handleHideModal = (event) => {
    event.stopPropagation(); // This doesn't work
    setModalState(false);
  };

  const runSignUpResult = useCallback(() => {
    handleHideModal();
    setUserStatus(`Thank you ${user} for signing up!`);
  }, [user]);

  const handleValidation = useCallback(
    (nameParameter) => {
      if (nameParameter.length === 0) {
        nameRef.current.focus();
        setInputError(true);
      } else {
        return [setInputError(false), runSignUpResult()];
      }
    },
    [runSignUpResult]
  );

  const handleSignUp = useCallback(
    (e) => {
      e.preventDefault();
      const name = nameRef.current.value;
      handleValidation(name);
    },
    [nameRef, handleValidation]
  );

  const handleChange = (e) => {
    setUser(e.target.value);
  };

  const modal = modalState ? (
    <Modal exitHandler={handleHideModal}>
      {modalId === "greeting" ? (
        <HelloWorld onClose={handleHideModal} user={user} />
      ) : (
        <SignUp
          onClose={handleHideModal}
          onSignUp={handleSignUp}
          handleChange={handleChange}
          user={user}
          ref={nameRef}
          inputError={inputError}
          modalId={modalId}
        />
      )}
    </Modal>
  ) : null;

  return (
    <div className="App">
      <AppHeader />

      <main className="app-body">
        <section className="modal-btns">
          <button id="greeting" className="btn" onClick={handleShowModal}>
            Greetings!
          </button>
          <button id="signup" className="btn" onClick={handleShowModal}>
            Sign Up
          </button>
        </section>
        <section>{modal}</section>
        <section className="user-status">
          <h3>{user.length === 0 ? null : userStatus}</h3>
        </section>
      </main>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
从“React”导入React;
常量HelloWorld=({user,onClose})=>{
返回(
问候语
X
{user?`Hello${user}!`:“问候!”}

); }; 导出默认HelloWorld;
模态内容2:

import React from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal-root");

function Modal({ exitHandler, children }) {
  return createPortal(
    <div className="modal" onClick={exitHandler}>
      {children}
    </div>,
    modalRoot
  );
}

export default Modal;
import React from "react";

const HelloWorld = ({ user, onClose }) => {
  
  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Greetings</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <p>{user ? `Hello ${user}!` : "Greetings!"}</p>
      </div>
    </div>
  );
};

export default HelloWorld;
import React, { forwardRef, useEffect } from "react";

const SignUp = forwardRef((props, ref) => {
  const { onClose, onSignUp, handleChange, inputError, user } = props;

  useEffect(() => {
    ref.current.focus();
  });

  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Sign Up</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <form onSubmit={onSignUp} className="modal-form">
          <label className="input-label">
            <span>Name:</span>
            <input
              type="text"
              onChange={handleChange}
              value={user}
              ref={ref}
              className={inputError === true ? "input-error" : null}
            />
          </label>
          <input className="btn" type="submit" value="Submit" />
        </form>
      </div>
    </div>
  );
});

export default SignUp;
const App = () => {
  const [modalState, setModalState] = useState(false);
  const [modalId, setModalId] = useState(null);
  const [inputError, setInputError] = useState(false);
  const [user, setUser] = useState("");
  const [userStatus, setUserStatus] = useState("");

  const nameRef = useRef(null);

  const handleShowModal = (e) => {
    const modalId = e.target.id.toString();
    return [setModalState(true), setModalId(modalId)];
  };

  const handleHideModal = (event) => {
    event.stopPropagation(); // This doesn't work
    setModalState(false);
  };

  const runSignUpResult = useCallback(() => {
    handleHideModal();
    setUserStatus(`Thank you ${user} for signing up!`);
  }, [user]);

  const handleValidation = useCallback(
    (nameParameter) => {
      if (nameParameter.length === 0) {
        nameRef.current.focus();
        setInputError(true);
      } else {
        return [setInputError(false), runSignUpResult()];
      }
    },
    [runSignUpResult]
  );

  const handleSignUp = useCallback(
    (e) => {
      e.preventDefault();
      const name = nameRef.current.value;
      handleValidation(name);
    },
    [nameRef, handleValidation]
  );

  const handleChange = (e) => {
    setUser(e.target.value);
  };

  const modal = modalState ? (
    <Modal exitHandler={handleHideModal}>
      {modalId === "greeting" ? (
        <HelloWorld onClose={handleHideModal} user={user} />
      ) : (
        <SignUp
          onClose={handleHideModal}
          onSignUp={handleSignUp}
          handleChange={handleChange}
          user={user}
          ref={nameRef}
          inputError={inputError}
          modalId={modalId}
        />
      )}
    </Modal>
  ) : null;

  return (
    <div className="App">
      <AppHeader />

      <main className="app-body">
        <section className="modal-btns">
          <button id="greeting" className="btn" onClick={handleShowModal}>
            Greetings!
          </button>
          <button id="signup" className="btn" onClick={handleShowModal}>
            Sign Up
          </button>
        </section>
        <section>{modal}</section>
        <section className="user-status">
          <h3>{user.length === 0 ? null : userStatus}</h3>
        </section>
      </main>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React,{forwardRef,useffect}来自“React”;
const SignUp=forwardRef((道具,ref)=>{
const{onClose,onSignUp,handleChange,inputeror,user}=props;
useffect(()=>{
ref.current.focus();
});
返回(
注册
X
姓名:
);
});
导出默认注册;
Main:

import React from "react";
import { createPortal } from "react-dom";

const modalRoot = document.getElementById("modal-root");

function Modal({ exitHandler, children }) {
  return createPortal(
    <div className="modal" onClick={exitHandler}>
      {children}
    </div>,
    modalRoot
  );
}

export default Modal;
import React from "react";

const HelloWorld = ({ user, onClose }) => {
  
  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Greetings</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <p>{user ? `Hello ${user}!` : "Greetings!"}</p>
      </div>
    </div>
  );
};

export default HelloWorld;
import React, { forwardRef, useEffect } from "react";

const SignUp = forwardRef((props, ref) => {
  const { onClose, onSignUp, handleChange, inputError, user } = props;

  useEffect(() => {
    ref.current.focus();
  });

  return (
    <div className="modal-content">
      <div className="modal-header">
        <div className="modal-title">
          <h2>Sign Up</h2>
        </div>
        <div className="modal-action">
          <button type="button" onClick={onClose}>X</button>
        </div>
      </div>
      <div className="modal-body">
        <form onSubmit={onSignUp} className="modal-form">
          <label className="input-label">
            <span>Name:</span>
            <input
              type="text"
              onChange={handleChange}
              value={user}
              ref={ref}
              className={inputError === true ? "input-error" : null}
            />
          </label>
          <input className="btn" type="submit" value="Submit" />
        </form>
      </div>
    </div>
  );
});

export default SignUp;
const App = () => {
  const [modalState, setModalState] = useState(false);
  const [modalId, setModalId] = useState(null);
  const [inputError, setInputError] = useState(false);
  const [user, setUser] = useState("");
  const [userStatus, setUserStatus] = useState("");

  const nameRef = useRef(null);

  const handleShowModal = (e) => {
    const modalId = e.target.id.toString();
    return [setModalState(true), setModalId(modalId)];
  };

  const handleHideModal = (event) => {
    event.stopPropagation(); // This doesn't work
    setModalState(false);
  };

  const runSignUpResult = useCallback(() => {
    handleHideModal();
    setUserStatus(`Thank you ${user} for signing up!`);
  }, [user]);

  const handleValidation = useCallback(
    (nameParameter) => {
      if (nameParameter.length === 0) {
        nameRef.current.focus();
        setInputError(true);
      } else {
        return [setInputError(false), runSignUpResult()];
      }
    },
    [runSignUpResult]
  );

  const handleSignUp = useCallback(
    (e) => {
      e.preventDefault();
      const name = nameRef.current.value;
      handleValidation(name);
    },
    [nameRef, handleValidation]
  );

  const handleChange = (e) => {
    setUser(e.target.value);
  };

  const modal = modalState ? (
    <Modal exitHandler={handleHideModal}>
      {modalId === "greeting" ? (
        <HelloWorld onClose={handleHideModal} user={user} />
      ) : (
        <SignUp
          onClose={handleHideModal}
          onSignUp={handleSignUp}
          handleChange={handleChange}
          user={user}
          ref={nameRef}
          inputError={inputError}
          modalId={modalId}
        />
      )}
    </Modal>
  ) : null;

  return (
    <div className="App">
      <AppHeader />

      <main className="app-body">
        <section className="modal-btns">
          <button id="greeting" className="btn" onClick={handleShowModal}>
            Greetings!
          </button>
          <button id="signup" className="btn" onClick={handleShowModal}>
            Sign Up
          </button>
        </section>
        <section>{modal}</section>
        <section className="user-status">
          <h3>{user.length === 0 ? null : userStatus}</h3>
        </section>
      </main>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
const-App=()=>{
const[modalState,setModalState]=useState(false);
const[modalId,setModalId]=useState(null);
const[inputError,setInputError]=useState(false);
const[user,setUser]=useState(“”);
const[userStatus,setUserStatus]=useState(“”);
const nameRef=useRef(null);
常量handleshowmodel=(e)=>{
const modalId=e.target.id.toString();
返回[setModalState(true),setModalId(modalId)];
};
const handleHideModal=(事件)=>{
event.stopPropagation();//这不起作用
setModalState(假);
};
const runSignUpResult=useCallback(()=>{
handleHideModal();
setUserStatus(`Thank you${user}感谢您的注册!`);
},[用户];
const handleValidation=useCallback(
(名称参数)=>{
如果(nameParameter.length==0){
nameRef.current.focus();
设置输入程序(真);
}否则{
返回[setInputError(false),runSignUpResult()];
}
},
[运行注册结果]
);
const handleSignUp=useCallback(
(e) =>{
e、 预防默认值();
const name=nameRef.current.value;
手推车(名称);
},
[名称参考,扶手电梯]
);
常数handleChange=(e)=>{
设置用户(如目标值);
};
常量模态=模态状态(
{modalId===“问候语”(
) : (
)}
):null;
返回(
问候语!
注册
{modal}
{user.length==0?null:userStatus}
);
};
const rootElement=document.getElementById(“根”);
render(,rootElement);

我认为问题在于react不理解父子关系,因为组件是在渲染后从外部添加的。合成事件处理由react本身完成。在处理内容可编辑div时,我遇到了类似的问题。我提出的解决方案是为这个孩子创建一个ref并使用addEventhandler。这是一项肮脏的工作,但似乎起了作用。也许对你有用。嗨@Sujit.Warrier你是说摩代尔的孩子?模态内容?模态就是我相信的那个孩子