Ik ontwikkel een applicatie waarin ik controleer of de gebruiker niet loggedIn
is. Ik moet het inlogformulier weergeven, anders dispatch
een action
die de route zou veranderen en een ander onderdeel zou laden. Hier is mijn code:
render() {
if (isLoggedIn) {
// dispatch an action to change the route
}
// return login component
<Login />
}
Hoe kan ik dit bereiken, aangezien ik de status binnen de functie render
niet kan wijzigen.
Antwoord 1, autoriteit 100%
Aangezien je react-router v4
gebruikt
Gebruik je component met withRouter
en gebruik history.push
van props om de route te wijzigen. U hoeft alleen gebruik te maken van withRouter
wanneer uw component de Router
-props niet ontvangt. Dit kan gebeuren in gevallen waarin uw component een genest kind is van een component die wordt weergegeven door de Router en u hebt de Router-rekwisieten er niet aan doorgegeven of wanneer het onderdeel helemaal niet aan de Router is gekoppeld en wordt weergegeven als een afzonderlijk onderdeel van de Routes.
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);
Belangrijke opmerking
Als u
withRouter
gebruikt om te voorkomen dat updates worden geblokkeerd door
shouldComponentUpdate
, is het belangrijk datwithRouter
de
component datshouldComponentUpdate
implementeert. Bijvoorbeeld, wanneer?
Redux gebruiken:// Dit omzeilt
shouldComponentUpdate
withRouter(connect(...)(MyComponent))
// Dit niet
connect(...)(withRouter(MyComponent))
of je zou Redirect kunnen gebruiken
import {withRouter} from 'react-router';
class App extends React.Component {
...
render() {
if(isLoggedIn) {
return <Redirect to="/home"/>
}
// return login component
return <Login />
}
}
Met react-router v2 or react-router v3
, kunt u gebruik maken van context
om de route dynamisch te wijzigen zoals
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;
of gebruik
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
Antwoord 2, autoriteit 12%
In react-router versie 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;
Antwoord 3, autoriteit 9%
Een ander alternatief is om dit af te handelen met behulp van asynchrone acties in Thunk-stijl (die veilig zijn/bijwerkingen mogen hebben).
Als je Thunk gebruikt, kun je hetzelfde history
-object in zowel je <Router>
-component als in de Thunk-acties injecteren met thunk.withExtraArgument
, zoals dit:
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)
Dan heb je in je actie-creators een history
-instantie die veilig te gebruiken is met ReactRouter, dus je kunt gewoon een normale Redux-gebeurtenis activeren als je niet bent ingelogd:
p>
// meanwhile... in action-creators.js
export const notLoggedIn = () => {
return (dispatch, getState, {history}) => {
history.push(`/login`)
}
}
Een ander voordeel hiervan is dat de url nu gemakkelijker te hanteren is, dus we kunnen omleidingsinformatie op de queryreeks plaatsen, enz.
Je kunt nog steeds proberen deze controle in je Render-methoden uit te voeren, maar als het problemen veroorzaakt, zou je kunnen overwegen om het in componentDidMount
te doen, of ergens anders in de levenscyclus (hoewel ik ook de wens begrijp om vast te houden met staatloze functionele componenten!)
Je kunt nog steeds Redux en mapDispatchToProps
gebruiken om de maker van de actie in je comptonent te injecteren, dus je component is nog steeds maar losjes verbonden met Redux.
Antwoord 4, autoriteit 5%
Dit is mijn adres loggedIn
. react-router v4
PrivateRoute is toegestaan voer path
in als de gebruiker is ingelogd en sla het token op in localStorge
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props => (localStorage.token) ? <Component {...props} /> : (
<Redirect
to={{
pathname: '/signin',
state: { from: props.location },
}}
/>
)
}
/>
);
}
Definieer hier alle paden in uw app
export default (
<main>
<Switch>
<Route exact path="/signin" component={SignIn} />
<Route exact path="/signup" component={SignUp} />
<PrivateRoute path="/" component={Home} />
</Switch>
</main>
);
Antwoord 5, autoriteit 2%
Degenen die problemen ondervinden bij het implementeren hiervan op react-router v4. Hier is een werkende oplossing om programmatisch door de react-app te navigeren.
geschiedenis.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
App.js OF Route.jsx. Geef geschiedenis door aan uw router.
import { Router, Route } from 'react-router-dom'
import history from './history'
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
Je kunt push()
gebruiken om te navigeren.
import history from './history'
...
render() {
if (isLoggedIn) {
history.push('/test') // this should change the url and re-render Test component
}
// return login component
<Login />
}
Allen Dank aan deze opmerking: https://github.com / Reacttraining / reageer-router / problemen / 3498 # IssueComment-301057248