【问题标题】:React-Router Redirect from a portal not redirecting来自门户的 React-Router 重定向未重定向
【发布时间】:2020-10-19 19:05:00
【问题描述】:

我正在开发一个用于 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;

这个modal只能在React-Router Route上查看/streams/:id/delete

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

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

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

到目前为止,我对这个项目的所有部分都有大量的注释Ncoughlin: Tag Twitch Clone

【问题讨论】:

  • Redirect 组件不是这样工作的,它需要作为可渲染 JSX 的一部分返回,而不是作为 onClick 回调的返回值。如果您能够访问 history 路由属性,或将其传递给模式,那么您可以强制发出导航。或者,您可以创建一些应该发生重定向的组件状态并有条件地呈现Redirect。您能否提供路由器代码,以便我们查看StreamDelete 是如何呈现的?
  • 是的,路由器在这里可用:App.js
  • 出于本文ncoughlin:programmatic navigationncoughlin:programmatic navigation 中的原因,我特别试图避免手动触摸历史道具
  • 是的。但是您从 onClick 返回重定向而不是示例从渲染返回重定向。
  • 避免使用history 属性来发出导航操作作为副作用,而不是RouteRedirect 组件似乎完全取决于意见。 IMO 他们都有自己的有效用例,完全使用其中一个或另一个将导致奇怪的代码模式(如下所示),您需要先保存一些状态,等待组件更新和重新渲染,然后 导航。这是一个浪费的渲染周期。那篇文章已有 2 年多的历史了,react 组件现在有了效果的概念,这不一定与总是先更新 some 状态才能做任何事情保持一致。

标签: javascript reactjs react-router react-portal


【解决方案1】:

由于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")
  );
};

建议的替代方案

不要将应用行为与展示(即模态)组件结合起来。根据模态框的一些“确认”,有条件地在StreamDelete 中呈现Redirect

const StreamDelete = () => {
  const [confirm, setConfirm] = useState(false);
  
  return confirm ? (
    <Redirect to="/" />
  ) : (
    <Modal onConfirm={() => setConfirm(true)} />
  );
};

【讨论】:

    【解决方案2】:

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

    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 : programmatic navigation

    中解释了这种技术

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2022-06-24
      • 1970-01-01
      • 2020-02-23
      • 2018-12-14
      • 2020-08-10
      相关资源
      最近更新 更多