React使用react-router-dom跳转时Info组件索引状态丢失无法返回上次实例
问题本质
Info组件的索引i是组件内部state,每次离开/info路由,Info组件会被React卸载,内部state会被清空,下次再进入/info路由时组件重新实例化,i就会初始化回0,这是问题的根本原因。
方案1:将索引存入路由参数(最推荐)
把当前展示的Info索引直接放到URL路径里,天然持久化,支持页面刷新、链接分享,完全符合路由设计规范。
修改代码:
- App.js 调整路由规则:
import "./styles.css"; import { BrowserRouter as Router, Switch, Route, Redirect } from "react-router-dom"; import Info from "./Info.js"; import Start from "./Start.js"; import End from "./End.js"; export default function App() { return ( <div className="App"> <Router> <Switch> <Route path="/" exact component={Start} /> {/* 新增带参数的info路由 */} <Route path="/info/:index" component={Info} /> {/* 访问无参数的/info默认跳转到第一个info */} <Route path="/info" exact render={() => <Redirect to="/info/0" />} /> <Route path="/End" component={End} /> </Switch> </Router> </div> ); }
- Info.js 移除内部索引state,直接从路由参数取值:
import React from "react"; import { Link } from "react-router-dom"; import arg from "./Infos.json"; export default class Info extends React.Component { arr = arg.map((elem) => elem); // 从路由参数获取当前索引,转成数字 getCurrentIndex = () => parseInt(this.props.match.params.index, 10); render() { const currentIndex = this.getCurrentIndex(); return ( <div> <h1>{this.arr[currentIndex].info}</h1> <Link to={currentIndex > 0 ? `/info/${currentIndex - 1}` : "/"}> <button type="button"> Back </button> </Link> {currentIndex < this.arr.length - 1 ? ( <Link to={`/info/${currentIndex + 1}`}> <button type="button"> Next </button> </Link> ) : ( // 跳转到End时携带最后一个info的索引 <Link to={{ pathname: "/End", state: { lastInfoIndex: currentIndex } }}> <button type="button"> Next </button> </Link> )} </div> ); } }
- End.js 读取跳转时携带的索引,返回对应info页:
import React from "react"; import { Link } from "react-router-dom"; export default class End extends React.Component { render() { // 取跳转时携带的最后一个info索引,兜底到最后一个 const lastInfoIndex = this.props.location.state?.lastInfoIndex ?? 3; return ( <div> <h1>End!</h1> <Link to={`/info/${lastInfoIndex}`}> <button>Back</button> </Link> {/* 也可以直接用history.goBack()实现原生回退,不需要带参数: <button onClick={() => this.props.history.goBack()}>Back</button> */} </div> ); } }
方案2:状态提升到父组件
如果不想把索引暴露在URL里,可以把索引状态提到公共父组件App里,Info组件通过props读写这个状态,组件卸载后状态还会保留在App中。
核心修改点:
- App组件新增state存储currentInfoIndex,提供修改方法传递给Info组件
- Info组件不再维护内部索引state,完全通过props操作父组件的状态
方案3:本地持久化存储
如果需要支持刷新页面后还保留上次浏览的Info位置,可以把索引存在localStorage里,Info组件初始化时从localStorage读取索引值,修改时同步更新到localStorage。
内容的提问来源于stack exchange,提问作者H Alrwasheda
相关产品推荐
相关产品推荐

