2

我正在为 React 实践开发一个 Twitch 克隆应用程序,并且我正在为用户想要删除视频流时创建一个模式弹出窗口。基本上他们有一个流列表,他们单击其中一个流上的删除按钮,然后使用ReactDOM.createPortal

这是删除按钮

import React from "react";

import Modal from "../Modal";

const StreamDelete = () => {

  return (
    <>
      <Modal />
    </>
  );
};

export default StreamDelete;

这是模态的代码

import React from "react";
import ReactDOM from "react-dom";
import { Redirect } from "react-router-dom";

const Modal = () => {

  
  return ReactDOM.createPortal(
    <div
      className="ui dimmer modals visible active"
      onClick={ () => {
        return <Redirect to="/" />;
      } }
    >
      <div className="ui standard modal visible active">
        <div className="header">Delete Stream</div>
        <div className="content">
          Are you sure you want to delete this stream?
        </div>
        <div className="actions">
          <button className="ui primary button">Delete</button>
          <button className="ui button">Cancel</button>
        </div>
      </div>
    </div>,
    document.querySelector("#modal")
  );
};

export default Modal;

模态的外观

此模式只能在 React-Router Route /streams/:id/delete上查看

我的预期行为是,当我单击深色背景时,我的onClick函数应该返回<Redirect to="/">应该关闭模态窗口的函数,因为它没有在该路由中呈现。

我得到的行为是单击深色背景不会重定向,尽管我也没有收到任何错误。

有关其他上下文,此项目的 GIT 存储库位于此处Glitch Client

到目前为止,我对这个项目的所有部分都有大量的笔记Ncoughlin:标记 Twitch 克隆

4

2 回答 2

2

由于是由组件StreamDelete直接渲染的Route

<Route path="/streams/:id/delete" exact component={StreamDelete} />

解决方案

它是通过路由道具,因此可以访问history道具。您可以使用它StreamDelete并将回调传递给模式以执行您想要的操作。

const StreamDelete = ({ history }) => {
  const doRedirect = () => history.replace("/");
  return (
    <>
      <Modal onDelete={doRedirect} />
    </>
  );
};

模态

const Modal = ({ onDelete }) => {
  return ReactDOM.createPortal(
    <div
      className="ui dimmer modals visible active"
      onClick={onDelete}
    >
      <div className="ui standard modal visible active">
        <div className="header">Delete Stream</div>
        <div className="content">
          Are you sure you want to delete this stream?
        </div>
        <div className="actions">
          <button className="ui primary button">Delete</button>
          <button className="ui button">Cancel</button>
        </div>
      </div>
    </div>,
    document.querySelector("#modal")
  );
};

选择

history如果您出于某种原因想避免使用该道具,则使用声明式实现。

在模态中使用一些“重定向”状态有条件地渲染一个Redirect.

const Modal = () => {
  const [redirect, setRedirect] = useState(false);

  if (redirect) {
    return <Redirect to="/" />;
  }
  
  return ReactDOM.createPortal(
    <div
      className="ui dimmer modals visible active"
      onClick={() => setRedirect(true)}
    >
      <div className="ui standard modal visible active">
        <div className="header">Delete Stream</div>
        <div className="content">
          Are you sure you want to delete this stream?
        </div>
        <div className="actions">
          <button className="ui primary button">Delete</button>
          <button className="ui button">Cancel</button>
        </div>
      </div>
    </div>,
    document.querySelector("#modal")
  );
};

建议的替代方案

不要将应用程序行为与展示(即模态)组件相结合。有条件地从模态RedirectStreamDelete获得一些“确认”。

const StreamDelete = () => {
  const [confirm, setConfirm] = useState(false);
  
  return confirm ? (
    <Redirect to="/" />
  ) : (
    <Modal onConfirm={() => setConfirm(true)} />
  );
};
于 2020-10-19T19:28:08.793 回答
0

通过遵循上面链接的文章中的示例,我也能够使其发挥作用。转换为组件,创建状态,使用点击处理程序触发一个帮助函数,该函数设置状态以有条件地呈现重定向。

import React from "react";
import ReactDOM from "react-dom";
import { Redirect } from "react-router-dom";

class Modal extends React.Component {
  state = {
    toDashboard: false,
  }

  handleClick = () => {
    this.setState(() => ({
      toDashboard: true
    }))
  }


  render() {
    if (this.state.toDashboard === true) {
      return <Redirect to='/' />
    }

    return ReactDOM.createPortal(
      
      <div
        className="ui dimmer modals visible active"
        onClick={ this.handleClick }
      >
        <div className="ui standard modal visible active">
          <div className="header">Delete Stream</div>
          <div className="content">
            Are you sure you want to delete this stream?
          </div>
          <div className="actions">
            <button className="ui primary button">Delete</button>
            <button className="ui button">Cancel</button>
          </div>
        </div>
      </div>,
      document.querySelector("#modal")
    );
  }
  
};

export default Modal;

这篇文章ui.dev 中解释了这种技术:程序化导航

于 2020-10-19T19:34:12.627 回答