我正在开发一个应用程序,我在其中检查用户是否loggedIn
我必须显示登录表单,否则dispatch
和action
将改变路由并加载其他零件。这是我的代码:
render() {
if (isLoggedIn) {
// dispatch an action to change the route
}
// return login component
<Login />
}
我怎样才能实现这一点,因为我无法改变渲染功能中的状态。
答案 0 :(得分:34)
考虑到您使用的是react-router v4
将您的组件与withRouter
一起使用,并使用道具中的history.push
来更改路线。只有在组件没有收到withRouter
道具时才需要使用Router
,这可能发生在组件是路由器呈现的组件的嵌套子级而您没有将Router支持传递给它,或者当组件根本没有链接到路由器时,它被呈现为路由中的单独组件。
import {withRouter} from 'react-router';
class App extends React.Component {
...
componenDidMount() {
// get isLoggedIn from localStorage or API call
if (isLoggedIn) {
// dispatch an action to change the route
this.props.history.push('/home');
}
}
render() {
// return login component
return <Login />
}
}
export default withRouter(App);
重要提示
如果您使用
withRouter
来阻止更新被阻止shouldComponentUpdate
,重要的是withRouter
包装。{1}} 实现shouldComponentUpdate
的组件。例如,何时 使用Redux://这可以解决
shouldComponentUpdate
withRouter(connect(...)(MyComponent))
//这不是
connect(...)(withRouter(MyComponent))
或者您可以使用重定向
import {withRouter} from 'react-router';
class App extends React.Component {
...
render() {
if(isLoggedIn) {
return <Redirect to="/home"/>
}
// return login component
return <Login />
}
}
使用react-router v2 or react-router v3
,您可以使用context
动态更改路径,如
class App extends React.Component {
...
render() {
if (isLoggedIn) {
// dispatch an action to change the route
this.context.router.push('/home');
}
// return login component
return <Login />
}
}
App.contextTypes = {
router: React.PropTypes.object.isRequired
}
export default App;
或使用
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
答案 1 :(得分:3)
在react-router版本4中:
import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
const Example = () => (
if (isLoggedIn) {
<OtherComponent />
} else {
<Router>
<Redirect push to="/login" />
<Route path="/login" component={Login}/>
</Router>
}
)
const Login = () => (
<h1>Form Components</h1>
...
)
export default Example;
答案 2 :(得分:2)
另一种方法是使用Thunk式异步操作(安全/允许有副作用)来处理这个问题。
如果您使用Thunk,则可以使用history
将<Router>
组件和Thunk操作注入相同的thunk.withExtraArgument
对象,如下所示:
import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'
import { createBrowserHistory } from "history"
import { applyMiddleware, createStore } from "redux"
import thunk from "redux-thunk"
const history = createBrowserHistory()
const middlewares = applyMiddleware(thunk.withExtraArgument({history}))
const store = createStore(appReducer, middlewares)
render(
<Provider store={store}
<Router history={history}>
<Route path="*" component={CatchAll} />
</Router
</Provider>,
appDiv)
然后在您的动作创建者中,您将拥有一个可以安全地与ReactRouter一起使用的history
实例,因此如果您未登录,则可以触发常规的Redux事件:
// meanwhile... in action-creators.js
export const notLoggedIn = () => {
return (dispatch, getState, {history}) => {
history.push(`/login`)
}
}
这样做的另一个好处是,现在,url更容易处理,因此我们可以在查询字符串上添加重定向信息等。
您可以尝试在Render方法中执行此检查,但如果它导致问题,您可以考虑在componentDidMount
或生命周期的其他位置执行此操作(尽管我也理解坚持使用无状态功能的愿望Compeonents!)
您仍然可以使用Redux和mapDispatchToProps
将动作创建器注入到您的组件中,因此您的组件仍然只是松散地连接到Redux。
答案 3 :(得分:0)
render(){
return (
<div>
{ this.props.redirect ? <Redirect to="/" /> :'' }
<div>
add here component codes
</div>
</div>
);
}
答案 4 :(得分:0)
在 react-router v4 上实施此操作时遇到的问题。这是一个用于以编程方式浏览React应用的可行解决方案。
history.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
App.js或Route.jsx。将历史记录作为道具传递给路由器。
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
您可以使用push()
进行导航。
import history from './history'
...
render() {
if (isLoggedIn) {
history.push('/test') // this should change the url and re-render Test component
}
// return login component
<Login />
}
全部感谢此评论:https://github.com/ReactTraining/react-router/issues/3498#issuecomment-301057248
答案 5 :(得分:0)
我建议您使用 connected-react-router (连接反应路由器) https://github.com/supasate/connected-react-router 如果需要的话,甚至可以从化简器/动作中进行导航。 它有据可查且易于配置
答案 6 :(得分:0)
这是我的手柄loggedIn
。 react-router v4
如果用户已登录,则允许PrivateRoute输入path
并将令牌保存到localStorge
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props => (localStorage.token) ? <Component {...props} /> : (
<Redirect
to={{
pathname: '/signin',
state: { from: props.location },
}}
/>
)
}
/>
);
}
在此处定义应用中的所有路径
export default (
<main>
<Switch>
<Route exact path="/signin" component={SignIn} />
<Route exact path="/signup" component={SignUp} />
<PrivateRoute path="/" component={Home} />
</Switch>
</main>
);
答案 7 :(得分:0)
我能够在无状态功能组件中使用history
,方法是使用withRouter(需要忽略打字稿警告):
import { withRouter } from 'react-router-dom';
...
type Props = { myProp: boolean };
// @ts-ignore
export const MyComponent: FC<Props> = withRouter(({ myProp, history }) => {
...
})