En la versión actual de React Router (v3) puedo aceptar una respuesta del servidor y usar browserHistory.push
para ir a la página de respuesta apropiada. Sin embargo, esto no está disponible en la v4 y no estoy seguro de cuál es la forma adecuada de manejarlo.
En este ejemplo, usando Redux, components / app-product-form.js llama this.props.addProduct(props)
cuando un usuario envía el formulario. Cuando el servidor devuelve un éxito, se lleva al usuario a la página del carrito.
// actions/index.js
export function addProduct(props) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
browserHistory.push('/cart'); // no longer in React Router V4
});
}
¿Cómo puedo redirigir a la página del carrito desde la función para React Router v4?
Puede utilizar los history
métodos fuera de sus componentes. Pruébelo de la siguiente manera.
Primero, cree un history
objeto usando el paquete de historial :
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Luego envuélvalo <Router>
( tenga en cuenta que debe usar en import { Router }
lugar de import { BrowserRouter as Router }
):
// src/index.jsx
// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/login">Login</Link></li>
</ul>
<Route exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
</div>
</Router>
</Provider>,
document.getElementById('root'),
);
Cambie su ubicación actual desde cualquier lugar, por ejemplo:
// src/actions/userActionCreators.js
// ...
import history from '../history';
export function login(credentials) {
return function (dispatch) {
return loginRemotely(credentials)
.then((response) => {
// ...
history.push('/');
});
};
}
UPD : También puede ver un ejemplo ligeramente diferente en las preguntas frecuentes de React Router .
React Router v4 es fundamentalmente diferente de v3 (y anteriores) y no puede hacer lo browserHistory.push()
que solía hacer.
Esta discusión parece relacionada si quieres más información:
- La creación de una nueva
browserHistory
no funcionará porque<BrowserRouter>
crea su propia instancia de historial y escucha los cambios en ella. Entonces, una instancia diferente cambiará la URL pero no actualizará el<BrowserRouter>
.browserHistory
react-router no está expuesto en v4, solo en v2.
En su lugar, tiene algunas opciones para hacer esto:
withRouter
componente de orden superiorEn su lugar, debe usar el withRouter
componente de orden superior y ajustarlo al componente que se enviará al historial. Por ejemplo:
import React from "react";
import { withRouter } from "react-router-dom";
class MyComponent extends React.Component {
...
myFunction() {
this.props.history.push("/some/Path");
}
...
}
export default withRouter(MyComponent);
Consulte la documentación oficial para obtener más información:
Usted puede obtener acceso a la
history
propiedades del objeto y el más cercano<Route>
que estámatch
a través del componente de orden superior withRouter. withRouter será volver a hacer su componente cada vez que cambia la ruta con los mismos apoyos que<Route>
rendir puntales:{ match, location, history }
.
context
APIUsar el contexto puede ser una de las soluciones más fáciles, pero al ser una API experimental, es inestable y no tiene soporte. Úselo solo cuando todo lo demás falle. He aquí un ejemplo:
import React from "react";
import PropTypes from "prop-types";
class MyComponent extends React.Component {
static contextTypes = {
router: PropTypes.object
}
constructor(props, context) {
super(props, context);
}
...
myFunction() {
this.context.router.history.push("/some/Path");
}
...
}
Eche un vistazo a la documentación oficial sobre contexto:
Si desea que su aplicación sea estable, no use el contexto. Es una API experimental y es probable que se rompa en futuras versiones de React.
Si insiste en usar el contexto a pesar de estas advertencias, intente aislar su uso del contexto en un área pequeña y evite usar la API de contexto directamente cuando sea posible para que sea más fácil actualizar cuando la API cambie.
Ahora, con react-router v5 puede usar el gancho del ciclo de vida useHistory de esta manera:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
leer más en: https://reacttraining.com/react-router/web/api/Hooks/usehistory
La forma más sencilla en React Router 4 es usar
this.props.history.push('/new/url');
Pero para usar este método, su componente existente debe tener acceso a history
object. Podemos acceder por
Si su componente está vinculado Route
directamente, entonces su componente ya tiene acceso al history
objeto.
p.ej:
<Route path="/profile" component={ViewProfile}/>
Aquí ViewProfile
tiene acceso a history
.
Si no está conectado Route
directamente.
p.ej:
<Route path="/users" render={() => <ViewUsers/>}
Luego tenemos que usar withRouter
una función de orden superior para deformar el componente existente.
ViewUsers
Componente interior
import { withRouter } from 'react-router-dom';
export default withRouter(ViewUsers);
Eso es todo ahora, su ViewUsers
componente tiene acceso al history
objeto.
ACTUALIZAR
2
- en este escenario, pase todas las rutas props
a su componente, y luego podemos acceder this.props.history
desde el componente incluso sin unHOC
p.ej:
<Route path="/users" render={props => <ViewUsers {...props} />}
Así es como lo hice:
import React, {Component} from 'react';
export default class Link extends Component {
constructor(props) {
super(props);
this.onLogout = this.onLogout.bind(this);
}
onLogout() {
this.props.history.push('/');
}
render() {
return (
<div>
<h1>Your Links</h1>
<button onClick={this.onLogout}>Logout</button>
</div>
);
}
}
Úselo this.props.history.push('/cart');
para redirigir a la página del carrito, se guardará en el objeto de historial.
Disfruta, Michael.
De acuerdo con la documentación de React Router v4 - Sesión de integración profunda de Redux
Se necesita una integración profunda para:
"poder navegar enviando acciones"
Sin embargo, recomiendan este enfoque como alternativa a la "integración profunda":
"En lugar de enviar acciones para navegar, puede pasar el objeto de historial proporcionado para enrutar componentes a sus acciones y navegar con él allí".
Para que pueda envolver su componente con el componente de orden superior withRouter:
export default withRouter(connect(null, { actionCreatorName })(ReactComponent));
que pasará la API de historial a props. Por lo que puede llamar al creador de la acción pasando el historial como parámetro. Por ejemplo, dentro de su ReactComponent:
onClick={() => {
this.props.actionCreatorName(
this.props.history,
otherParams
);
}}
Luego, dentro de sus actions / index.js:
export function actionCreatorName(history, param) {
return dispatch => {
dispatch({
type: SOME_ACTION,
payload: param.data
});
history.push("/path");
};
}
Pregunta desagradable, me tomó bastante tiempo, pero finalmente, la resolví de esta manera:
Envuelva su contenedor withRouter
y pase el historial a su acción en mapDispatchToProps
función. En acción, use history.push ('/ url') para navegar.
Acción:
export function saveData(history, data) {
fetch.post('/save', data)
.then((response) => {
...
history.push('/url');
})
};
Envase:
import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
return {
save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));
Esto es válido para reaccionar Router v4.x .
this.context.history.push
no trabajará.
Me las arreglé para hacer que push funcionara así:
static contextTypes = {
router: PropTypes.object
}
handleSubmit(e) {
e.preventDefault();
if (this.props.auth.success) {
this.context.router.history.push("/some/Path")
}
}
Ofrezco una solución más en caso de que valga la pena para otra persona.
Tengo un history.js
archivo donde tengo lo siguiente:
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history
A continuación, en mi raíz donde defino mi enrutador, uso lo siguiente:
import history from '../history'
import { Provider } from 'react-redux'
import { Router, Route, Switch } from 'react-router-dom'
export default class Root extends React.Component {
render() {
return (
<Provider store={store}>
<Router history={history}>
<Switch>
...
</Switch>
</Router>
</Provider>
)
}
}
Finalmente, en mi actions.js
, importo el historial y utilizo pushLater
import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)
De esta manera, puedo impulsar nuevas acciones después de las llamadas a la API.
¡Espero eso ayude!
En este caso, estás pasando accesorios a tu procesador. Entonces puedes simplemente llamar
props.history.push('/cart')
Si este no es el caso, aún puede pasar el historial de su componente
export function addProduct(data, history) {
return dispatch => {
axios.post('/url', data).then((response) => {
dispatch({ type: types.AUTH_USER })
history.push('/cart')
})
}
}
Aquí está mi truco (este es mi archivo de nivel raíz, con un pequeño redux mezclado allí, aunque no lo estoy usando react-router-redux
):
const store = configureStore()
const customHistory = createBrowserHistory({
basename: config.urlBasename || ''
})
ReactDOM.render(
<Provider store={store}>
<Router history={customHistory}>
<Route component={({history}) => {
window.appHistory = history
return (
<App />
)
}}/>
</Router>
</Provider>,
document.getElementById('root')
)
Luego puedo usarlo en window.appHistory.push()
cualquier lugar que quiera (por ejemplo, en mis funciones de tienda redux / thunks / sagas, etc.) que esperaba poder usar, window.customHistory.push()
pero por alguna razón react-router
nunca pareció actualizarse a pesar de que la URL cambió. Pero de esta manera tengo los react-router
usos EXACTOS de instancia . No me encanta poner cosas en el ámbito global, y esta es una de las pocas cosas con las que haría eso. Pero es mejor que cualquier otra alternativa que haya visto en mi opinión.
Si está utilizando Redux, le recomendaría utilizar el paquete npm react-router-redux . Le permite enviar acciones de navegación de la tienda Redux.
Debe crear una tienda como se describe en su archivo Léame .
El caso de uso más sencillo:
import { push } from 'react-router-redux'
this.props.dispatch(push('/second page'));
Segundo caso de uso con contenedor / componente:
Envase:
import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import Form from '../components/Form';
const mapDispatchToProps = dispatch => ({
changeUrl: url => dispatch(push(url)),
});
export default connect(null, mapDispatchToProps)(Form);
Componente:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class Form extends Component {
handleClick = () => {
this.props.changeUrl('/secondPage');
};
render() {
return (
<div>
<button onClick={this.handleClick}/>
</div>Readme file
);
}
}
Pude lograr esto usando bind()
. Quería hacer clic en un botón index.jsx
, publicar algunos datos en el servidor, evaluar la respuesta y redirigir a success.jsx
. Así es como lo resolví ...
index.jsx
:
import React, { Component } from "react"
import { postData } from "../../scripts/request"
class Main extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
this.postData = postData.bind(this)
}
handleClick() {
const data = {
"first_name": "Test",
"last_name": "Guy",
"email": "[email protected]"
}
this.postData("person", data)
}
render() {
return (
<div className="Main">
<button onClick={this.handleClick}>Test Post</button>
</div>
)
}
}
export default Main
request.js
:
import { post } from "./fetch"
export const postData = function(url, data) {
// post is a fetch() in another script...
post(url, data)
.then((result) => {
if (result.status === "ok") {
this.props.history.push("/success")
}
})
}
success.jsx
:
import React from "react"
const Success = () => {
return (
<div className="Success">
Hey cool, got it.
</div>
)
}
export default Success
Entonces, al vincularme this
a postData
in index.jsx
, pude acceder this.props.history
en request.js
... luego puedo reutilizar esta función en diferentes componentes, solo tengo que asegurarme de recordar incluir this.postData = postData.bind(this)
en el constructor()
.
así que la forma en que lo hago es: - en lugar de redirigir el uso history.push
, solo uso el Redirect
componente de react-router-dom
Cuando use este componente, puede simplemente pasar push=true
, y se encargará del resto
import * as React from 'react';
import { Redirect } from 'react-router-dom';
class Example extends React.Component {
componentDidMount() {
this.setState({
redirectTo: '/test/path'
});
}
render() {
const { redirectTo } = this.state;
return <Redirect to={{pathname: redirectTo}} push={true}/>
}
}
Utilice la devolución de llamada. ¡Funcionó para mí!
export function addProduct(props, callback) {
return dispatch =>
axios.post(`${ROOT_URL}/cart`, props, config)
.then(response => {
dispatch({ type: types.AUTH_USER });
localStorage.setItem('token', response.data.token);
callback();
});
}
En el componente, solo tiene que agregar la devolución de llamada
this.props.addProduct(props, () => this.props.history.push('/cart'))
React router V4 ahora permite que el accesorio de historial se use de la siguiente manera:
this.props.history.push("/dummy",value)
Entonces se puede acceder al valor siempre que la propiedad de ubicación esté disponible como
state:{value}
estado no componente.
puedes usarlo así como lo hago para iniciar sesión y muchas cosas diferentes
class Login extends Component {
constructor(props){
super(props);
this.login=this.login.bind(this)
}
login(){
this.props.history.push('/dashboard');
}
render() {
return (
<div>
<button onClick={this.login}>login</login>
</div>
)
/*Step 1*/
myFunction(){ this.props.history.push("/home"); }
/**/
<button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go
Home</button>
paso uno envuelve tu aplicación en el enrutador
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
Ahora toda mi aplicación tendrá acceso a BrowserRouter. Paso dos: importo Route y luego paso esos accesorios. Probablemente en uno de sus archivos principales.
import { Route } from "react-router-dom";
//lots of code here
//somewhere in my render function
<Route
exact
path="/" //put what your file path is here
render={props => (
<div>
<NameOfComponent
{...props} //this will pass down your match, history, location objects
/>
</div>
)}
/>
Ahora, si ejecuto console.log (this.props) en el archivo js de mi componente, debería obtener algo que se vea así
{match: {…}, location: {…}, history: {…}, //other stuff }
Paso 2 Puedo acceder al objeto del historial para cambiar mi ubicación
//lots of code here relating to my whatever request I just ran delete, put so on
this.props.history.push("/") // then put in whatever url you want to go to
Además, solo soy un estudiante de bootcamp de programación, así que no soy un experto, pero sé que tú también puedes usar
window.location = "/" //wherever you want to go
Corrígeme si me equivoco, pero cuando lo probé, volví a cargar la página completa, lo que pensé que anulaba todo el punto de usar React.
Crea una personalizada Router
con la suya propia browserHistory
:
import React from 'react';
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory();
const ExtBrowserRouter = ({children}) => (
<Router history={history} >
{ children }
</Router>
);
export default ExtBrowserRouter
A continuación, en su raíz donde define su Router
, use lo siguiente:
import React from 'react';
import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';
//Use 'ExtBrowserRouter' instead of 'BrowserRouter'
import ExtBrowserRouter from './ExtBrowserRouter';
...
export default class Root extends React.Component {
render() {
return (
<Provider store={store}>
<ExtBrowserRouter>
<Switch>
...
<Route path="/login" component={Login} />
...
</Switch>
</ExtBrowserRouter>
</Provider>
)
}
}
Finalmente, importe history
donde lo necesite y úselo:
import { history } from '../routers/ExtBrowserRouter';
...
export function logout(){
clearTokens();
history.push('/login'); //WORKS AS EXPECTED!
return Promise.reject('Refresh token has expired');
}
Si desea usar el historial mientras pasa una función como un valor a la propiedad de un componente, con react-router 4 puede simplemente desestructurar la history
propiedad en el atributo de representación del <Route/>
componente y luego usarhistory.push()
<Route path='/create' render={({history}) => (
<YourComponent
YourProp={() => {
this.YourClassMethod()
history.push('/')
}}>
</YourComponent>
)} />
Nota: Para que esto funcione, debe envolver el componente BrowserRouter de React Router alrededor de su componente raíz (por ejemplo, que podría estar en index.js)
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Captura de pantalla del video de Facebook Para aquellos de ustedes que pueden ser demasiado jóvenes para saber esto, antes de que Ice-T fuera una gran estrella en Ley y orden: Unidad de víctimas especiales, era uno de los mejores raperos gangsta de Los Ángeles de todos los tiempos. De hecho, estaba haciendo gangsta rap antes que N.
Imagen a través de WHAS 11 Algunas cosas realmente podrían tener "carga racial" sin ser racistas. Pero en los principales medios de comunicación, el primero suele ser un código para el segundo.
Foto: Sony Taraji P. Henson, experta tanto en reacciones cáusticas como en expresiones con los ojos húmedos de abrumador conflicto interno, es una actriz dinámica.
Foto: Ronald Martinez / Getty El grandote de los Spurs, LaMarcus Aldridge está teniendo quizás la temporada más eficiente de su carrera mientras reemplaza a Kawhi Leonard como el jugador principal de San Antonio. Mientras que los Warriors y los Rockets están en una carrera armamentista para ver quién puede disparar 100 triples en un juego primero, los Spurs están escondidos detrás de Houston.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.