javascript - property - Navegar mediante programación usando react-router
title label html (8)
Estoy desarrollando una aplicación en la que compruebo si el usuario no ha
loggedIn
Tengo que mostrar el formulario de inicio de sesión; de lo contrario,
dispatch
una
action
que cambiaría la ruta y cargaría otro componente.
Aquí está mi código:
render() {
if (isLoggedIn) {
// dispatch an action to change the route
}
// return login component
<Login />
}
¿Cómo puedo lograr esto ya que no puedo cambiar los estados dentro de la función de renderizado?
Aquellos que enfrentan problemas para implementar esto en react-router v4 . Aquí hay una solución de trabajo para navegar a través de la aplicación Reaccionar mediante programación.
history.js
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props => (localStorage.token) ? <Component {...props} /> : (
<Redirect
to={{
pathname: ''/signin'',
state: { from: props.location },
}}
/>
)
}
/>
);
}
App.js O Route.jsx. Pase la historia como accesorio a su enrutador.
export default (
<main>
<Switch>
<Route exact path="/signin" component={SignIn} />
<Route exact path="/signup" component={SignUp} />
<PrivateRoute path="/" component={Home} />
</Switch>
</main>
);
Puede usar
push()
para navegar.
render(){
return (
<div>
{ this.props.redirect ? <Redirect to="/" /> :'''' }
<div>
add here component codes
</div>
</div>
);
}
Todo gracias a este comentario: https://github.com/ReactTraining/react-router/issues/3498#issuecomment-301057248
En react-router versión 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;
Este es mi identificador
loggedIn
.
react-router v4
PrivateRoute permite ingresar la
path
si el usuario ha iniciado sesión y guarda el token en
localStorge
import createHistory from ''history/createBrowserHistory''
export default createHistory()
Defina todas las rutas en su aplicación aquí
import { Router, Route } from ''react-router-dom''
import history from ''./history''
...
<Router history={history}>
<Route path="/test" component={Test}/>
</Router>
Le sugeriría que use router de reacción conectado https://github.com/supasate/connected-react-router que ayuda a realizar la navegación incluso desde reductores / acciones si lo desea. Está bien documentado y es fácil de configurar
Otra alternativa es manejar esto usando acciones asincrónicas de estilo Thunk (que son seguras / se les permite tener efectos secundarios).
Si usa Thunk, puede inyectar el mismo objeto de
history
tanto en su componente
<Router>
como en las acciones de Thunk usando
thunk.withExtraArgument
, de esta manera:
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)
Luego, en sus creadores de acción, tendrá una instancia de
history
segura para usar con ReactRouter, por lo que puede desencadenar un evento Redux normal si no está conectado:
// meanwhile... in action-creators.js
export const notLoggedIn = () => {
return (dispatch, getState, {history}) => {
history.push(`/login`)
}
}
Otra ventaja de esto es que la url es más fácil de manejar, por lo que podemos poner información de redireccionamiento en la cadena de consulta, etc.
Puede intentar seguir haciendo esta verificación en sus métodos de Render, pero si causa problemas, puede considerar hacerlo en
componentDidMount
o en cualquier otra parte del ciclo de vida (¡aunque también entiendo el deseo de seguir con los competidores funcionales sin estado!)
Todavía puede usar Redux y
mapDispatchToProps
para inyectar el creador de la acción en su componente, por lo que su componente todavía está conectado libremente a Redux.
Pude usar el
history
dentro del componente funcional sin estado, usando withRouter de la siguiente manera (necesario ignorar la advertencia de mecanografía):
import { withRouter } from ''react-router-dom'';
...
type Props = { myProp: boolean };
// @ts-ignore
export const MyComponent: FC<Props> = withRouter(({ myProp, history }) => {
...
})
Teniendo en cuenta que está utilizando
react-router v4
Use su componente con
withRouter
y use
history.push
de los accesorios para cambiar la ruta.
withRouter
usar
withRouter
solo cuando su componente no recibe los accesorios del
Router
, esto puede suceder en los casos en que su componente sea un elemento anidado de un componente representado por el enrutador y no le haya pasado los accesorios del enrutador o cuando el componente no está vinculado al enrutador y se representa como un componente separado de las rutas.
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);
Nota IMPORTANTE
Si está utilizando
withRouter
para evitar que las actualizaciones sean bloqueadas porshouldComponentUpdate
, es importante quewithRouter
envuelva el componente que implementashouldComponentUpdate
. Por ejemplo, cuando usa Redux:// Esto se
shouldComponentUpdate
withRouter(connect(...)(MyComponent))
// Esto no lo hace
connect(...)(withRouter(MyComponent))
o podrías usar Redirect
import {withRouter} from ''react-router'';
class App extends React.Component {
...
render() {
if(isLoggedIn) {
return <Redirect to="/home"/>
}
// return login component
return <Login />
}
}
Con
react-router v2 or react-router v3
, puede utilizar el
context
para cambiar dinámicamente la ruta como
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;
o usar
import { browserHistory } from ''react-router'';
browserHistory.push(''/some/path'');
import history from ''./history''
...
render() {
if (isLoggedIn) {
history.push(''/test'') // this should change the url and re-render Test component
}
// return login component
<Login />
}