如何使用 react-router 重定向到另一条路由?
Posted
技术标签:
【中文标题】如何使用 react-router 重定向到另一条路由?【英文标题】:How to do a redirect to another route with react-router? 【发布时间】:2016-04-16 14:11:06 【问题描述】:我正在尝试使用 react-router(version ^1.0.3)做一个简单的重定向到另一个视图,我只是累了。
import React from 'react';
import Router, Route, Link, RouteHandler from 'react-router';
class HomeSection extends React.Component
static contextTypes =
router: PropTypes.func.isRequired
;
constructor(props, context)
super(props, context);
handleClick = () =>
console.log('HERE!', this.contextTypes);
// this.context.location.transitionTo('login');
;
render()
return (
<Grid>
<Row className="text-center">
<Col md=12 xs=12>
<div className="input-group">
<span className="input-group-btn">
<button onClick=this.handleClick type="button">
</button>
</span>
</div>
</Col>
</Row>
</Grid>
);
;
HomeSection.contextTypes =
location()
React.PropTypes.func.isRequired
export default HomeSection;
我只需要将使用发送到“/login”就可以了。
我能做什么?
控制台错误:
Uncaught ReferenceError: PropTypes is not defined
包含我的路线的文件
// LIBRARY
/*eslint-disable no-unused-vars*/
import React from 'react';
/*eslint-enable no-unused-vars*/
import Route, IndexRoute from 'react-router';
// COMPONENT
import Application from './components/App/App';
import Contact from './components/ContactSection/Contact';
import HomeSection from './components/HomeSection/HomeSection';
import NotFoundSection from './components/NotFoundSection/NotFoundSection';
import TodoSection from './components/TodoSection/TodoSection';
import LoginForm from './components/LoginForm/LoginForm';
import SignupForm from './components/SignupForm/SignupForm';
export default (
<Route component=Application path='/'>
<IndexRoute component=HomeSection />
<Route component=HomeSection path='home' />
<Route component=TodoSection path='todo' />
<Route component=Contact path='contact' />
<Route component=LoginForm path='login' />
<Route component=SignupForm path='signup' />
<Route component=NotFoundSection path='*' />
</Route>
);
【问题讨论】:
嗨!您能否发布您的routes
定义,以及是否有理由不使用Link
组件?另外,请提及您遇到的错误。
而不是按钮,<Link to="/login">Log In</Link>
?
另外你使用的是什么版本的 react-router?程序重定向的代码在主要版本之间发生了变化。
对于Uncaught ReferenceError
,你调用的是PropTypes
,但你不导入它,你需要导入PropTypes本身或使用React.PropTypes
@JoshDavidMiller 好点,但我不会感到惊讶 react-router
api 在 5 分钟内更改.. 哈哈开玩笑,但只是部分
【参考方案1】:
1) react-router > V5 useHistory
hook:
如果您有React >= 16.8
和功能组件,您可以使用useHistory
hook from react-router。
import React from 'react';
import useHistory from 'react-router-dom';
const YourComponent = () =>
const history = useHistory();
const handleClick = () =>
history.push("/path/to/push");
return (
<div>
<button onClick=handleClick type="button" />
</div>
);
export default YourComponent;
2) 反应路由器 > V4 withRouter
HOC:
正如 @ambar 在 cmets 中提到的,React-router 自 V4.0 以来已经改变了他们的代码库。这是文档 - official, withRouter
import React, Component from 'react';
import withRouter from "react-router-dom";
class YourComponent extends Component
handleClick = () =>
this.props.history.push("path/to/push");
render()
return (
<div>
<button onClick=this.handleClick type="button">
</div>
);
;
export default withRouter(YourComponent);
3) React-router browserHistory
您可以使用 react-router BrowserHistory
实现此功能。代码如下:
import React, Component from 'react';
import browserHistory from 'react-router';
export default class YourComponent extends Component
handleClick = () =>
browserHistory.push('/login');
;
render()
return (
<div>
<button onClick=this.handleClick type="button">
</div>
);
;
4) Redux connected-react-router
如果你已经用 redux 连接了你的组件,并且已经配置了 connected-react-router 你所要做的就是
this.props.history.push("/new/url");
即,您不需要withRouter
HOC 将history
注入到组件道具中。
// reducers.js
import combineReducers from 'redux';
import connectRouter from 'connected-react-router';
export default (history) => combineReducers(
router: connectRouter(history),
... // rest of your reducers
);
// configureStore.js
import createBrowserHistory from 'history';
import applyMiddleware, compose, createStore from 'redux';
import routerMiddleware from 'connected-react-router';
import createRootReducer from './reducers';
...
export const history = createBrowserHistory();
export default function configureStore(preloadedState)
const store = createStore(
createRootReducer(history), // root reducer with router state
preloadedState,
compose(
applyMiddleware(
routerMiddleware(history), // for dispatching history actions
// ... other middlewares ...
),
),
);
return store;
// set up other redux requirements like for eg. in index.js
import Provider from 'react-redux';
import Route, Switch from 'react-router';
import ConnectedRouter from 'connected-react-router';
import configureStore, history from './configureStore';
...
const store = configureStore(/* provide initial state if any */)
ReactDOM.render(
<Provider store=store>
<ConnectedRouter history=history>
<> /* your usual react-router v4/v5 routing */
<Switch>
<Route exact path="/yourPath" component=YourComponent />
</Switch>
</>
</ConnectedRouter>
</Provider>,
document.getElementById('root')
);
// YourComponent.js
import React, Component from 'react';
import connect from 'react-redux';
...
class YourComponent extends Component
handleClick = () =>
this.props.history.push("path/to/push");
render()
return (
<div>
<button onClick=this.handleClick type="button">
</div>
);
;
export default connect(mapStateToProps = , mapDispatchToProps = )(YourComponent);
【讨论】:
似乎 'browserHistory' 不再是 react-router 的一部分了。 BrowserRouter没有推送功能 @ambar @johnnyodonnellreact-router-dom
确实
这是最好的答案。您应该将此标记为正确的。
对于 useHistory --> 是否需要先在某处指定路径? DOM 应该如何知道要针对哪个路由渲染哪个组件?【参考方案2】:
对于简单的答案,您可以使用来自react-router
的Link
组件,而不是button
。有一些方法可以改变 JS 中的路线,但似乎你在这里不需要。
<span className="input-group-btn">
<Link to="/login" />Click to login</Link>
</span>
要在 1.0.x 中以编程方式执行此操作,您可以在 clickHandler 函数中这样做:
this.history.pushState(null, 'login');
取自升级文档here
您应该将this.history
由react-router
放置在您的路由处理程序组件上。如果它是routes
定义中提到的子组件,您可能需要进一步传递它
【讨论】:
这是一个很酷的解决方案,但我不使用它的原因是因为我需要先做一种验证,所以我需要把它放在一个函数中,比如:@987654330 @ 所以这就是为什么我把它放在一个 onClick 函数中 你也可以在 JSX 中这样做:validation && <Link to="/login" />Click to login</Link>
。如果验证为假,则不会呈现任何内容。
我知道你的意思,但我需要按钮在那里,如果验证为真,则重定向,否则会出现错误消息。
@TheUnnamed 我更新了答案以展示如何在 JS 中做到这一点
>Uncaught TypeError: Cannot read property 'pushState' of undefined【参考方案3】:
如何使用 react-router 重定向到另一个路由?
例如,当用户点击链接 <Link to="/" />Click to route</Link>
时,react-router 将寻找 /
,您可以使用 Redirect to
并将用户发送到其他地方,例如登录路由。
从docs 到ReactRouterTraining:
渲染
<Redirect>
将导航到新位置。新的 location 将覆盖历史堆栈中的当前位置,例如 服务器端重定向 (HTTP 3xx) 可以。
import Route, Redirect from 'react-router'
<Route exact path="/" render=() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)/>
to: 字符串,要重定向到的 URL。
<Redirect to="/somewhere/else"/>
to:对象,要重定向到的位置。
<Redirect to=
pathname: '/login',
search: '?utm=your+face',
state: referrer: currentLocation
/>
【讨论】:
提供的解决方案抛出错误<Redirect> elements are for router configuration only and should not be rendered
。【参考方案4】:
最简单的网络解决方案!
2020 年最新版本 确认与:
"react-router-dom": "^5.1.2"
"react": "^16.10.2"
使用useHistory()
钩子!
import React from 'react';
import useHistory from "react-router-dom";
export function HomeSection()
const history = useHistory();
const goLogin = () => history.push('login');
return (
<Grid>
<Row className="text-center">
<Col md=12 xs=12>
<div className="input-group">
<span className="input-group-btn">
<button onClick=goLogin type="button" />
</span>
</div>
</Col>
</Row>
</Grid>
);
【讨论】:
太棒了,正在寻找钩子的方法来做到这一点!即使我的 IDE 显示“无法解析符号 ...”警告,它确实有效! 太棒了,这就是我一直在寻找的,它在这里工作【参考方案5】:我知道这是一个老问题,但对于 2021 年及之后的 React Router V6 来到这里的人来说,useHistory 不再从 react-router-dom 导出,您必须改为导入 useNavigate。示例代码如下:
import useNavigate from "react-router-dom"
在你的反应类或功能组件中:
const navigate = useNavigate()
navigate("/404")
【讨论】:
【参考方案6】:使用 react-router v2.8.1(可能还有其他 2.x.x 版本,但我还没有测试过),您可以使用此实现进行路由器重定向。
import Router from 'react-router';
export default class Foo extends Component
static get contextTypes()
return
router: React.PropTypes.object.isRequired,
;
handleClick()
this.context.router.push('/some-path');
【讨论】:
有时:this.context.router.history.push('/some-path');【参考方案7】:最简单的解决方案是:
import Redirect from 'react-router';
<Redirect to='/componentURL' />
【讨论】:
但我收到一个错误:不变式失败:您不应该在以上是关于如何使用 react-router 重定向到另一条路由?的主要内容,如果未能解决你的问题,请参考以下文章
从 Symfony2 中的 routing.yml 将一条路由重定向(301)到另一条路由
承诺后如何使用react-router重定向到另一个url?