后退按钮在 React 中显示空白页

Posted

技术标签:

【中文标题】后退按钮在 React 中显示空白页【英文标题】:Back button displays blank page in React 【发布时间】:2020-11-06 14:05:30 【问题描述】:

我正在尝试使用浏览器中的后退按钮,以便用户可以在我的 react 应用程序中顺利返回。它有时适用于特定组件。例如,当我从 Supervisores 到 Anfitrion 时它可以工作,但是当我从 Anfitrion 到 Suprvisores 或任何动态路线时它都不起作用。 这是我的路由器中的内容。

    <Router>

    <Switch>

            <Route exact path="/Anfitrion" component=PropiedadesRegistradas/>
            <Route path='/AgregarPropiedad' component=AgregarPropiedad />
            <Route path= "/AreasRegistradas/:propertyId" component=AreasRegistradas/>
            <Route path= "/ItemsAreasRegistradas/:propertyId" component=ItemsAreasRegistradas/>            
            <Route path="/ElementosDeArea/:areaId" component = ElementosDeArea />
            <Route path="/AgregarItems/:areaId/:propertyId" component = AgregarItems />
            <Route path="/AgregarArea/:propertyId" component = AgregarArea />

            <Route path="/supervisores" component=Supervisores/>
            <Route path="/historial" component=Historial/>
            <Route path="/desinfeccion" component=Desinfeccion/>
            <Route path="/folios" component=Folios/>    

            <Route path="/areasRegistradas" component=AreasRegistradas/>
            <Route path= "/agregarSupervisor" component=AgregarSupervisor/>
            <Route path="/detalle/:servicio/:hostId" component=Detalle />
            <Route render=()=> <h3>Not found</h3>/>

          </Switch>
    </Router>


这是我尝试使用 useHistory Hook 的方法,但是当我点击按钮时它会显示一个黑页:

import React from 'react'
import Button from '@material-ui/core/Button';
import  useHistory  from 'react-router-dom'



export default function AgregarItems(match, props)
    let history = useHistory()
    return(
        <div>
        <Button onClick=() => history.goBack()>Atrás</Button>
        </div>
    )

当我使用浏览器的后退和前进按钮时,它也会显示一个空白页面。我正在阅读有关 React 路由器的历史记录,但我还没有发现任何有用的东西,当我这样做时,它是针对 React Router v3 的。

感谢您的帮助!

我正在使用:

"react-dom": "^16.13.1", “反应路由器”:“^5.2.0”, "react-router-dom": "^5.2.0",

【问题讨论】:

我需要再次仔细检查这一点,但您是否尝试将组件包装在 withRouter 中,例如:import withRouter from 'react-router-dom'; const AgregarItems = () =&gt; history.goBack() .... export default withRouter(AgregarItems); 【参考方案1】:

我通过从我的 rails 应用程序中删除 turbolinks 解决了这个问题。信用:page is not rendering when I click back button with react-router

【讨论】:

就是这样。它解决了我在 Rails API/React 前端项目中的问题【参考方案2】:

刚刚使用 CRA 进行了测试。看看并试试这个。 您可能不需要使用withRouter

文件: ./PageOne.js

import React from 'react';
import  Link  from 'react-router-dom'

const PageOne = props => <div><h1>Click below</h1><Link to="/page2">Page 2</Link></div>;

export default PageOne;

文件: ./PageTwo.js

import React from 'react';

const PageTwo = props => <div><h1>Click Below</h1><button onClick=() => props.history.goBack()>Go Back</button></div>;

export default PageTwo;

文件: ./index.js

import React from 'react';
import ReactDOM from 'react-dom';
import  BrowserRouter, Route, Switch  from 'react-router-dom'
import PageOne from './PageOne';
import PageTwo from './PageTwo';

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <Switch>
        <Route exact path="/" component=PageOne />
        <Route exact path="/page2" component=PageTwo />
      </Switch>
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

========== 更新 ===========

对于作为抽象&lt;PrivateRoute&gt;的角色的路由中间件

点击下面的运行代码sn-p,看看它是如何获得权限的。

// IMPORTS
const  useState  = React;
// *** only allows HashRouter
// But replace with BrowserRouter
const  HashRouter, Switch, Route, Link, Redirect  = ReactRouterDOM;

/**
 *
 */
const NotPermitted = props => <div><h1>Not Permitted</h1><p>You need to be</p> <code>admin@admin.com</code><p>&nbsp;</p><Link to="/">Go Back Home</Link></div>;

/**
 *
 */
const AdminOnly = props => <div><h1>Admin Only</h1><p>You should only see this is your email is "admin@admin.com"</p></div>;

/**
 *
 */
const Dashboard = props => <div><h1>Dashboard</h1><p>Links</p><ul><li><Link to="/private">Private Page</Link></li><li><Link to="/adminonly">Admin Only</Link></li></ul></div>;

/**
 *
 */
const Login = props => 
  const onSubmit = event => 
    event.preventDefault();
    if (props.login) 
      props.login(
        email: event.target.email.value,
        password: event.target.password.value
      );
    
  

  return <div>
    <h1>Login</h1>
    <form onSubmit=onSubmit>
      <p><input type="text" name="email" placeholder="Email" /></p>
      <p><input type="password" name="password" placeholder="Password" /></p>
      <p><button type="submit">Submit</button></p>
    </form>
    </div>


/**
 *
 */
const PrivatePage = props => <div><h1>Private Page</h1><p>Anyone logged in can see this page.</p><Link to="/">Go Back Home</Link></div>;

/**
 *
 */
const PrivateRoute = props => 
  const  component: Component, permitted, user, ...rest  = props;
  return (
    <Route
      ...rest
      render=(routeProps) => 
        user
          ? permitted
            ? <Component ...routeProps />
            : <Redirect to="/notpermitted" />
          : <Redirect to="/login" />
      
    />
  );


/**
 *
 */
const App = props => 
  const [user, setUser] = useState(null);
  
  const login = ( email, password ) => 
    setUser(
      email,
    );
  
  
  const logout = () => 
    setUser(null);
  
  
  return <div>
      user && <button onClick=logout>Logout</button>
      <Switch>
        <Route exact path="/" render=() => user ? <Redirect to="/dashboard" /> : <Redirect to="/login" /> />
        <Route exact path="/login" render=(routeProps) => !user ? <Login login=login ...routeProps /> : <Redirect to="/dashboard" /> />
        <PrivateRoute user=user permitted=true exact path="/dashboard" component=Dashboard />
        <PrivateRoute user=user permitted=user && user.email === 'admin@admin.com' exact path="/adminonly" component=AdminOnly />
        <PrivateRoute user=user permitted=true exact path="/private" component=PrivatePage />
        <PrivateRoute user=user permitted=true exact path="/notpermitted" component=NotPermitted />
      </Switch>
      <hr />
      user && <p><small>Debug JSON</small></p>
      user && <pre><code>JSON.stringify(user, null, ' ')</code></pre>
      <p><small>Redirect Tests</small></p>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/login">Login</Link></li>
        <li><Link to="/dashboard">Dashboard</Link></li>
        <li><Link to="/adminonly">Admin Only</Link></li>
        <li><Link to="/private">Private</Link></li> 
        <li><Link to="/notpermitted">Not Permitted</Link></li> 
      </ul>
  </div>


/**
 *
 */
const Index = props => 
  return <div>
    <HashRouter>
      <App />
    </HashRouter>
  </div>


ReactDOM.render(<Index />, document.querySelector('#root'));
body 
font-family: Arial, sans-serif;
padding: 20px;
margin: 0;


form 
display: block;


input 
  height: 40px;
  padding: 0 12px;
  border-radius: 4px;
  border: 1px solid #efefef;
  min-width: 200px;


button 
  display: block;
  height: 40px;
  padding: 0 20px;
  background: blue;
  color: white;
  border-radius: 4px;
  border: none;


pre 
display: block;
margin-top: 20px;


code 
display: block;
  background: #efefef;
  padding: 20px;


h1 
  font-size: 21px;
  padding-bottom: 20px;
  border-bottom: 1px solid #efefef;
  margin-bottom: 20px;


hr 
border: none;
height: 1px;
background: #efefef;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-router/umd/react-router.min.js"></script>
<script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>

<div id="root"></div>

【讨论】:

我试过这个,实际上我使用 history.goBack() 从一个组件转到主组件“/Anfitrion”并且它有效!但由于某种原因它如果我想去别的地方就不行了。 你所说的“去别的地方”是什么意思,比如去不同的路线?示例history.push("/page3") ? 没错!我的意思是,我可以毫无问题地执行 history.push(),但是当我单击浏览器上的后退按钮时,它会显示一个空白页面 这是本地开发(标准 CRA)还是生产构建(纱线构建...等)? 我认为这与之前的身份验证过程有关。因为我直接重定向到“/Anfitrion”。关于身份验证后如何使用反应路由器的任何想法?【参考方案3】:

我知道这个问题很老,但我会发布我的答案,因为我遇到了这个问题,我希望找到更简单的解决方案。

用例:React 作为前端,Ruby on Rails 6 作为后端。

如果您在浏览器中按“返回”并且您的 React 应用呈现空白页面,您有两种解决方案:

    Remove TurboLinks gem 调整您的应用,使其与 TurboLinks 一起使用。

如果你想删除 TurboLinks:

    从 Gemfile 中移除 gem 'turbolinks', '~> 5' 从 app/assets/javascript/application.js 中删除 //= 需要 turbolinks 从 app/views/layouts/application.html.erb 中删除 'data-turbolinks-track': 'reload' (x2) 运行 yarn remove turbolinks 运行 rails tmp:cache:clear

第 4 步是与 Rails 5 的主要区别。 致 this 帖子。

如果你想保留 TurboLinks

你的 React 应用的 index.js 看起来像这样:

document.addEventListener('DOMContentLoaded', () => 
  ReactDOM.render(
    <App />,
    document.body.appendChild(document.createElement('div')),
  )
)

你必须让它看起来像这样:

document.addEventListener('turbolinks:load', () => 
  ReactDOM.render(
    <App />,
    document.body.appendChild(document.createElement('div')),
  )
)

基本上,您将事件侦听器从 DOMContentLoaded 更改为 turbolinks:load

如果您停在这里,您会注意到现在当您在应用程序中来回前进时,组件会在同一页面上多次呈现。

要解决此问题,请进入application.html.erb 并在&lt;head&gt; 标签中添加此代码的sn-p

<meta name='turbolinks-cache-control' content='no-cache'>

恭喜!现在,您的 React on Rails 应用程序可以与 TurboLinks 一起使用。

【讨论】:

以上是关于后退按钮在 React 中显示空白页的主要内容,如果未能解决你的问题,请参考以下文章

为什么Android应用程序在退出带有后退按钮的应用程序时显示空白屏幕React Native Navigation?

为啥 IE 11 显示空白页渲染反应应用

登录脚本显示空白页

运行时反应故事书空白页

Service Worker 在 React 应用程序中刷新后导致空白页

在 react-router v4 的嵌套路由中看到空白页