React+TypeScript+Ionic项目动画结束后跳转登录页报错如何解决
问题背景
我尝试在初始动画执行完成后将用户跳转至登录页,动画时长为2秒,因此我设置了3秒延迟的setTimeout执行跳转逻辑,但运行后提示无法加载http://localhost/pages/Login.tsx页面,抛出net::ERR_INVALID_RESPONSE错误。
初始代码
import React, { useEffect } from 'react'; import { IonApp } from '@ionic/react'; import "./css/main.css"; /* Core CSS required for Ionic components to work properly */ import '@ionic/react/css/core.css'; /* Basic CSS for apps built with Ionic */ import '@ionic/react/css/normalize.css'; import '@ionic/react/css/structure.css'; import '@ionic/react/css/typography.css'; /* Optional CSS utils that can be commented out */ import '@ionic/react/css/padding.css'; import '@ionic/react/css/float-elements.css'; import '@ionic/react/css/text-alignment.css'; import '@ionic/react/css/text-transformation.css'; import '@ionic/react/css/flex-utils.css'; import '@ionic/react/css/display.css'; /* Theme variables */ import './theme/variables.css'; const App: React.FC = () => { useEffect(() => { setTimeout(() => { console.log("set timeout") var goToLogin: HTMLElement = document.querySelector("#goToLogin") as HTMLElement; goToLogin?.click(); // window.location = "/pages/Login.tsx"; }, 3000); }, []); return( <IonApp class="app"> <a id="goToLogin" href="./pages/Login.tsx"></a> <div> <svg id="core-logo" width="117" height="60" viewBox="0 0 307 157" fill="#fff" xmlns="http://www.w3.org/2000/svg"> <path d="M67.824 78.088H88.56C88.56 83.08 87.744 87.544 86.112 91.48C84.48 95.416 82.224 98.776 79.344 101.56C76.464 104.344 73.056 106.456 69.12 107.896C65.184 109.638 153.848 212.094 153.932 212.742 154.004C213.414 154.1 214.074 154.148 214.722 1288.974 133.336 289.998 132.248C291.054 131.16 291.582 129.48 291.582 127.208ZM283.758 128.744V132.008H281.694V122.312H285.15C286.654 122.312 287.694 122.584 288.27 123.128C288.878 123.64 289.182 124.44 289.182 125.528C289.182 126.328 289.006 126.984 288.654 127.496C288.302 127.976 287.774 128.312 287.07 128.504L289.422 132.008H286.83L284.862 128.744H283.758ZM287.07 125.528C287.07 125.08 286.926 124.744 286.638 124.52C286.35 124.296 285.854 124.184 285.15 124.184H283.758V127.016H285.15C285.854 127.016 286.35 126.904 286.638 126.68C286.926 126.424 287.07 126.04 287.07 125.528Z" fill="white"/> </svg> </div> </IonApp> ); }; export default App;
项目文件结构

第一次修改后情况
修改后代码如下:
const App: React.FC = () => { let history = useHistory(); useEffect(() => { setTimeout(() => { history.push("/login"); }, 3000); }, []); return( <IonApp class="app"> <IonReactRouter> <IonRouterOutlet> <Route exact path="/login" component={Login} /> </IonRouterOutlet> </IonReactRouter> <div> <svg id="core-logo" width="117" height="60" viewBox="0 0 307 157" fill="#fff" xmlns="http://www.w3.org/2000/svg"> <path d="M67.824 78.088H88.56C88.56 83.08 87.744 87.544 86.112 91.48C84.48 95.416 82.224 98.776 12 287.07 128.504L289.422 132.008H286.83L284.862 128.744H283.758ZM287.07 125.528C287.07 125.08 286.926 124.744 286.638 124.52C286.35 124.296 285.854 124.184 285.15 124.184H283.758V127.016H285.15C285.854 127.016 286.35 126.904 286.638 126.68C286.926 126.424 287.07 126.04 287.07 125.528Z" fill="white"/> </svg> </div> </IonApp> ); };
同时在index.tsx中使用BrowserRouter包裹了App组件:
ReactDOM.render( <React.StrictMode> <Router> <App /> </Router> </React.StrictMode>, document.getElementById('root') );
第二次修改后问题
移除了index.tsx中的Router包裹,修改后代码如下:
ReactDOM.render( <React.StrictMode> {/* <Router> */} <App /> {/* </Router> */} </React.StrictMode>, document.getElementById('root') );
同时将useEffect替换为以下逻辑:
useIonViewWillEnter(() => { setTimeout(() => { history.push("/login"); }, 3000); });
现在可以在Chrome开发者工具的地址栏中正常导航,但每次渲染新页面时App组件都会重复渲染,同时抛出如下错误:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
解决方案
- 初始
net::ERR_INVALID_RESPONSE错误的原因是你直接跳转.tsx源码文件,浏览器无法直接解析执行TSX文件,前端路由跳转的是逻辑路径,不是本地源码文件路径,必须通过路由库实现跳转。 - 无限渲染报错的原因是
useIonViewWillEnter没有加空依赖数组,每次组件进入视图都会执行该钩子,跳转后App组件仍在渲染,就会反复触发跳转逻辑,陷入死循环。同时需要添加定时器清理逻辑,避免组件卸载后定时器仍执行抛出异常:
useIonViewWillEnter(() => { const timer = setTimeout(() => { history.push("/login"); }, 3000); return () => clearTimeout(timer); }, []);
- 优化路由结构:当前你把开屏动画和路由容器都放在App组件里,跳转到登录页后开屏动画的SVG仍会和登录页一起渲染。建议把开屏逻辑抽为独立页面,路由配置拆分如下:
// App.tsx 仅保留路由容器 import React from 'react'; import { IonApp, IonRouterOutlet } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import { Route } from 'react-router-dom'; import Splash from './pages/Splash'; // 原开屏逻辑抽为该组件 import Login from './pages/Login'; const App: React.FC = () => { return ( <IonApp> <IonReactRouter> <IonRouterOutlet> <Route exact path="/" component={Splash} /> <Route exact path="/login" component={Login} /> </IonRouterOutlet> </IonReactRouter> </IonApp> ); }; export default App;
- 不需要在index.tsx中额外添加Router包裹,
IonReactRouter已经内置了路由能力,双层Router嵌套会导致路由逻辑异常。
内容的提问来源于stack exchange,提问作者Inês Borges
相关产品推荐
相关产品推荐

