В текущей версии React Router (v3) я могу принимать ответ сервера и использовать browserHistory.push
для перехода на соответствующую страницу ответа. Однако в версии v4 такой возможности нет, и я не уверен, какой способ будет правильным.
В этом примере, используя Redux, components/app-product-form.js вызывает this.props.addProduct(props)
, когда пользователь отправляет форму. Когда сервер возвращает успех, пользователь переходит на страницу корзины.
// 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
});
}
Как сделать перенаправление на страницу "Корзина" из функции для React Router v4?
React Router v4 принципиально отличается от v3 (и более ранних версий), и вы не можете делать browserHistory.push()
как раньше.
Это обсуждение кажется связанным, если вы хотите больше информации:
- Создание новой
browserHistory
не будет работать, потому что<BrowserRouter>
создает свой собственный экземпляр истории и слушает изменения в нем. Таким образом, другой экземпляр изменит url, но не обновит<BrowserRouter>
.browserHistory
не раскрывается react-router в v4, только в v2.
Вместо этого у вас есть несколько вариантов, как это сделать:
withRouter
.Вместо этого вы должны использовать компонент высокого порядка withRouter
и обернуть его в компонент, который будет выталкивать в историю. Например:
<!-- language: lang-js -->
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);
Ознакомьтесь с официальной документацией для получения дополнительной информации:
context
Использование контекста может быть одним из самых простых решений, но, будучи экспериментальным API, он нестабилен и не поддерживается. Используйте его только тогда, когда все остальное не работает. Вот пример:
<!-- language: lang-js -->
import React from "react";
import PropTypes from "prop-types";
class MyComponent extends React.Component {
static contextTypes = {
маршрутизатор: PropTypes.object
}
constructor(props, context) {
super(props, context);
}
...
myFunction() {
this.context.router.history.push("/some/Path");
}
...
}
Посмотрите официальную документацию по контексту:
Если вы хотите, чтобы ваше приложение было стабильным, не используйте контекст. Это экспериментальный API, и он, скорее всего, сломается в будущих выпусках React.
Если вы настаиваете на использовании контекста, несмотря на эти предупреждения, постарайтесь изолировать использование контекста в небольшой области и по возможности избегайте прямого использования API контекста, чтобы было проще обновить его при изменении API.
Вы можете использовать методы "истории" за пределами ваших компонентов. Попробовать следующим образом.
Во-первых, создать "историю" объекта, используемого пакет истории:
// src/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Затем заверните его в <маршрутизатор>
(обратите внимание, вы должны использовать импорт { роутер }
вместо импорт { BrowserRouter как маршрутизатор }
):
// 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'),
);
Изменить вашего текущего местоположения с любого места, например:
// src/actions/userActionCreators.js
// ...
import history from '../history';
export function login(credentials) {
return function (dispatch) {
return loginRemotely(credentials)
.then((response) => {
// ...
history.push('/');
});
};
}
<ч>
<б>УПД</б>: вы также можете увидеть немного другой пример в реагируете FAQ маршрутизатор.
Вот как я это сделал:
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>
);
}
}
Используйте this.props.history.push('/cart');
для перенаправления на страницу корзины, она будет сохранена в объекте истории.
Наслаждайтесь, Майкл.
По данным реагировать маршрутизатор документации В4 - обертывание глубокая интеграция сессии
Глубокая интеграция необходима для:
"и уметь ориентироваться по диспетчеризации действий"и
Тем не менее, они рекомендуют этот подход в качестве альтернативы в "глубокой интеграции и":
"Ну, а не диспетчерской движения для навигации вы можете сдать историю объекта, поставленного маршрута компоненты, чтобы ваши действия и ориентироваться с ним там.&и"
Так что вы можете обернуть ваш компонент с withRouter высокий компонент заказа:
экспорт по умолчанию withRouter(подключать(значение null, { actionCreatorName })(ReactComponent));`
который пройдет в API историю реквизит. Так можно назвать творцом действий, проходящих в историю как парам. Например, в вашем ReactComponent:
onClick={() => {
this.props.actionCreatorName(
this.props.history,
otherParams
);
}}
Затем внутри вашего actions/index.js:
export function actionCreatorName(history, param) {
return dispatch => {
dispatch({
type: SOME_ACTION,
payload: param.data
});
history.push("/path");
};
}
Простой способ в маршрутизатор реагируют 4-использовать
this.props.history.push('/new/url');
Но чтобы использовать этот метод, ваш существующие компонент должен иметь доступ к "истории" объекта. Мы можем получить доступ
например:
<маршруту пути=" в профиль" и компонент={ViewProfile}/>
Здесь ViewProfile` имеет доступ к "истории".
например:
<маршруту пути=" по - /пользователи" и рендер={() =>
Тогда мы должны использовать withRouter
, а высшее фикцию того, чтобы деформировать существующий компонент.
Внутри `ViewUsers компонент
импорт { withRouter } с 'реагировать-маршрутизатор-дом';`
экспорт withRouter по умолчанию(ViewUsers);`
Что'ы сейчас, компонент ViewUsers
имеет доступ к "истории" объекта.
Обновление
2
- в этом случае, пройти весь маршрут пропсами к вашему компу, и тогда мы сможем открыть это.реквизит.истории из компонента даже без специальной`
например:
<Route path="/users" render={props => <ViewUsers {...props} />}
Противный вопрос, мне потребовалось довольно много времени, но в конце концов, я решил это так:
Оберните контейнер с withRouter и передают истории ваших действий в функции mapDispatchToProps`. В действии использование истории.нажимаем('/в URL') для навигации.
Действия:
export function saveData(history, data) {
fetch.post('/save', data)
.then((response) => {
...
history.push('/url');
})
};
Контейнер:
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));
Это справедливо для маршрутизатор реагировать В4.х.
this.context.history.push
не будет работать.
Мне удалось заставить push работать следующим образом:
static contextTypes = {
router: PropTypes.object
}
handleSubmit(e) {
e.preventDefault();
if (this.props.auth.success) {
this.context.router.history.push("/some/Path")
}
}
В этом случае вы'повторного прохождения реквизит на ваш преобразователь. Поэтому можно просто позвонить
props.history.push('/cart')
Если это'т так, вы можете по-прежнему сдают историю из своего компонента
export function addProduct(data, history) {
return dispatch => {
axios.post('/url', data).then((response) => {
dispatch({ type: types.AUTH_USER })
history.push('/cart')
})
}
}
Я предлагаю еще одно решение в случае, если это ценно для кого-то другого.
У меня есть файл `history.js где у меня есть следующие:
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
history.pushLater = (...args) => setImmediate(() => history.push(...args))
export default history
Далее, на мой корень, откуда я определяю мой роутер я использую следующие:
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>
)
}
}
Наконец, на моем `actions.js-я импортировать историю и pushLater
import history from './history'
export const login = createAction(
...
history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
...)
Таким образом, я могу подтолкнуть к новым действиям после вызовов API.
Надеюсь, что это помогает!
Теперь с реагировать-маршрутизатор У5 можно использовать useHistory жизненного цикла крюк такой:
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>
);
}
подробнее на: https://reacttraining.com/react-router/web/api/Hooks/usehistory
Использование Обратного Вызова. Он работал для меня!
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();
});
}
В компоненту, вы просто должны добавить обратного вызова
this.props.addProduct(props, () => this.props.history.push('/cart'))
Мне удалось сделать это с помощью привязки(). Я хотел нажать на кнопку в индекс.jsx
, опубликовать некоторые данные на сервер, оценить ответ и перенаправить к успеху.jsx`. Здесь's, как я поняла это...
индекс.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")
}
})
}
успех.jsx
:
import React from "react"
const Success = () => {
return (
<div className="Success">
Hey cool, got it.
</div>
)
}
export default Success
Поэтому, связывая это " до "postData" в " индекс.jsx, я был в состоянии получить доступ к
этому.реквизит.историяв
request.js... затем я могу использовать эту функцию в различных компонентов, просто чтобы убедиться, что я помню, чтобы включить это.postData = postData.привязать(это)
в конструктор()
.
в Если вы используете клетку, то я бы рекомендовал использовать НПМ пакет реагировать-маршрутизатор-возвращение. Это позволяет направить Redux в магазине действия навигации.
Вы должны создать магазин, как описано в файле сведений.
Самый простой вариант использования:
import { push } from 'react-router-redux'
this.props.dispatch(push('/second page'));
Второй вариант использования с контейнером/компонент:
Контейнер:
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);
Компонент:
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
);
}
}
Здесь's мой хак (это мой корневой файл, с немного обертывание смешанные в там, хотя я'м не с помощью реагировать-маршрутизатор-возвращение
):
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')
)
Затем я могу использовать окно.appHistory.метод push()
где захочу (например, в моем Redux в магазине функции/преобразователи/саг и т. д.) Я надеялся, я мог бы просто использовать окно.customHistory.метод push ()
, но по какой-то причине реагировать-маршрутизатор никогда не казалось обновление, даже если URL-адрес изменился. Но этот способ я точный экземпляр
реагировать-маршрутизатор использует. Я не'т люблю раскладывать вещи в глобальной области видимости, и это одна из немногих вещей, которые я'd сделать это. Но это's лучше, чем любой другой альтернативы я'вэ видел ИМО.
Реагировать маршрутизатор В4 теперь позволяет проп истории будет использоваться, как показано ниже:
this.props.history.push("/dummy",value)
Значение может быть доступно везде, где место проп доступен как состояние:{значение}` не составляющей государственную.
так как я делаю это:
от
реагировать-маршрутизатор-дом При использовании этого компонента вы можете просто передать сигнал=true
, тогда он будет заботиться об остальномимпорт * как реагировать от 'реагировать'; импорт { перенаправление } с 'реагировать-маршрутизатор-дом'; пример класса расширяет реагировать.Компонент { componentDidMount() { это.выполнении функция setState({ redirectTo: '/испытания/путь' }); }
рендер() { константный { redirectTo } = этот.государства;
возвращение <перенаправление={{путь: redirectTo}} пуш={истинный}/> } }
Шаг первый обернуть приложение в маршрутизатор
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
Теперь все мои приложения будут иметь доступ к BrowserRouter. Шаг второй импортировать маршрут, а затем передать эти подпорки. Вероятно, в один из главных файлов.
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>
)}
/>
Теперь если я запускаю консоль.журнал(это.реквизит) в мой компонент JS файл, который я должен сделать что-то вроде этого
{match: {…}, location: {…}, history: {…}, //other stuff }
Шаг 2 я могу получить доступ к объекту истории, чтобы изменить мое местоположение
//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
Также Я'м просто кодирование коллоквиума студент, поэтому я'м не эксперт, но я знаю, что вы можете также использовать
window.location = "/" //wherever you want to go
Поправьте меня, если я'м неправильно, но когда я проверил, что это перезагрузка всей страницы, которые я думал, что победил весь смысл реагировать.
вы можете использовать его так, как я делаю это для входа и Мэнни разные вещи
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>
)
Создать пользовательский маршрутизатор
со своим 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
Далее, на корень, где вы определите свой "маршрутизатор", используйте следующее:
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>
)
}
}
Наконец, импорт "история", где вам нужно, и использовать его:
import { history } from '../routers/ExtBrowserRouter';
...
export function logout(){
clearTokens();
history.push('/login'); //WORKS AS EXPECTED!
return Promise.reject('Refresh token has expired');
}
/*Step 1*/
myFunction(){ this.props.history.push("/home"); }
/**/
<button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go
Home</button>