React Router调用history.push跳转URL变更但组件未渲染问题求助
问题原因
核心问题是你的代码中嵌套了两层完全独立的Router实例:
- index.tsx中已经通过
createBrowserHistory创建了自定义history实例,传递给了外层的Router组件 - App.tsx中又额外引入了
BrowserRouter as Router,再次包裹了路由规则,BrowserRouter内部会自行维护独立的history实例,和你外层传入的自定义history完全隔离 - 你在LoginForm中调用的是外层自定义history的
push方法,只会更新外层Router的状态,内层的BrowserRouter感知不到地址变化,因此不会触发路由重匹配,也就不会渲染对应的组件,只有URL会被外层修改。
解决方法
任选以下一个方案即可:
方案1:删除App.tsx里的Router包裹
直接去掉App.tsx里的<Router>标签,保留内部的Navbar、Switch、Route逻辑即可,外层已经有Router提供路由上下文了,修改后App.tsx的结构如下:
import { Link, Route, Switch } from "react-router-dom" // 去掉外层多余的Router标签 <> <Navbar /> <Switch> <Route exact path="/" component={Home} /> <Route exact path="/profiles" component={UsersDashboard} /> <Route path={`/profiles/:username`} component={UserProfile} /> <Route exact path="/login" component={LoginForm} /> <Route exact path="/contact" component={Contact} /> <Route exact path="/about" component={About} /> <Route component={NotFound} /> </Switch> </>
该方案可以保留你现有的自定义history实例的用法,不需要修改LoginForm里的跳转逻辑。
方案2:统一使用BrowserRouter,移除自定义history
如果你不需要对history做特殊自定义操作,可以删掉index.tsx里的自定义Router和history相关逻辑,外层直接用BrowserRouter,同时LoginForm用react-router-dom提供的useHistory hook获取当前路由上下文的history实例做跳转:
- 修改index.tsx:
import { BrowserRouter as Router } from "react-router-dom" import { store, StoreContext } from "./app/stores/store" ReactDOM.render( <React.StrictMode> <StoreContext.Provider value={store}> <Router> <App /> </Router> </StoreContext.Provider> </React.StrictMode>, document.getElementById("root") )
- 还是需要删除App.tsx里多余的外层Router标签,调整方式和方案1一致
- 修改LoginForm的跳转逻辑:
import { useHistory } from "react-router-dom" export default function LoginForm() { const history = useHistory() // 从当前路由上下文获取history实例 const [values, setValues] = useState({ username: "", email: "", password: "", }) const handleSubmit = (e: FormEvent<HTMLFormElement>) => { e.preventDefault() login(values).then(() => history.push("/profiles")) } // 其余逻辑保持不变 }
内容的提问来源于stack exchange,提问作者frankiie
相关产品推荐
相关产品推荐

