React调用history.push仅更新URL不跳转路由的问题咨询
问题根因
出现该现象的核心原因是你手动传入WButton的history实例,没有和Router内部的状态更新监听关联,调用push时仅修改了地址栏URL,没有触发Router组件的重渲染,因此Switch不会重新匹配路由、渲染对应的Next组件。
放在Home组件内正常的原因是:Route渲染的组件默认会注入Router上下文中的路由相关属性,拿到的history实例本身就和Router的更新监听绑定,调用push会主动触发Router重渲染。forceRefresh: true生效的原因是该配置会让每次导航触发整页刷新,走浏览器原生的页面加载逻辑,不需要依赖Router的内部更新,但会丢失单页应用的无刷新体验。
可行解决方案
- 方案1:使用路由高阶组件/钩子获取
history实例
不要手动传递自己创建的history给WButton,而是通过路由提供的API直接从上下文获取实例:- 如果是
react-router-dom v5版本:用withRouter高阶组件包裹WButton
此时不需要在顶层给import { withRouter } from 'react-router-dom' class WButton extends React.Component { handleClick = () => { this.props.history.push('/next') } // 其他逻辑 } export default withRouter(WButton)WButton传history属性,组件会自动拿到正确的实例。 - 如果是
react-router-dom v6版本:在函数组件内使用useNavigate钩子实现导航import { useNavigate } from 'react-router-dom' function WButton() { const navigate = useNavigate() const handleClick = () => { navigate('/next') } // 其他逻辑 }
- 如果是
- 方案2:匹配
history包版本
如果你一定要使用外部创建的history实例,需要确保你项目中单独安装的history包版本,和react-router-dom依赖的history版本完全一致:react-router-dom v5对应history v4版本- 版本不兼容会导致
history的变更事件无法被Router监听到,就会出现仅改URL不重渲染的问题
- 方案3:适配v6版本的HistoryRouter
如果你使用的是react-router-dom v6,普通的Router组件已经不支持直接传入外部history实例,需要改用unstable_HistoryRouter:import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom' const history = createBrowserHistory() function App() { return ( <HistoryRouter history={history}> <WButton history={history}/> <Switch> <Route exact path='/' component={Home}/> <Route exact path='/next' component={Next}/> </Switch> </HistoryRouter> ) }
内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

