React-router v4 this.props.history.push(...) не работает
Я пытаюсь маршрутизировать программно с помощью this.props.history.push(..)
, но он не работает.
Здесь маршрутизатор:
import {
BrowserRouter as Router,
Route
} from 'react-router-dom';
<Router>
<Route path="/customers/" exact component={CustomersList} />
<Route path="/customers/:id" exact component="{Customer} />
</Router>
В CustomerList отображается список клиентов. Нажатие на клиента (li) должно сделать маршрут приложения к клиенту:
import { withRouter } from 'react-router'
class Customers extends Component {
static propTypes = {
history: PropTypes.object.isRequired
}
handleCustomerClick(customer) {
this.props.history.push(`/customers/${customer.id}`);
}
render() {
return(
<ul>
{ this.props.customers.map((c) =>
<li onClick={() => this.handleCustomerClick(c)} key={c.id}>
{c.name}
</li>
</ul>
)
}
}
//connect to redux to get customers
CustomersList = withRouter(CustomersList);
export default CustomersList;
Код является частичным, но в полной мере иллюстрирует ситуацию.
Случается, что адресная строка браузера изменяется в соответствии с history.push(..), но представление не обновляется, компонент Customer не отображается, а CustomerList все еще существует. Любые идеи?
Ответы
Ответ 1
Поэтому я пришел к этому вопросу в надежде получить ответ, но безрезультатно. я использовал
const { history } = this.props;
history.push("/thePath")
В том же проекте все заработало как положено. После дальнейших экспериментов и некоторых сравнений и контрастов я понял, что этот код не будет работать, если он вызывается внутри вложенного компонента. Поэтому только компонент визуализированной страницы может вызывать эту функцию для правильной работы.
Найти рабочую песочницу здесь
- история: v4.7.2
- реагировать: v16.0.0
- Реакт-Дом: v16.0.0
- response-router-dom: v4.2.2
Ответ 2
Кажется, что в последней версии реагирующего маршрутизатора ситуация немного изменилась. Теперь вы можете получить доступ к истории через контекст. this.context.history.push('/path')
Также см. ответы на эту проблему github: https://github.com/ReactTraining/react-router/issues/4059
Ответ 3
Вы можете попробовать загрузить дочерний компонент с историей. Для этого пропустите "историю" через реквизит. Что-то вроде того:
return (
<div>
<Login history={this.props.history} />
<br/>
<Register/>
</div>
)
Ответ 4
Похоже, старый вопрос, но все еще актуален.
Я думаю, что это заблокированная проблема обновления.
Основная проблема заключается в том, что новый URL (маршрут) должен отображаться тем же компонентом (Costumers
), который используется в данный момент (текущий URL).
Таким образом, решение довольно простое, сделайте URL окна в качестве реквизита, чтобы у реакции был шанс обнаружить изменение реквизита (и, следовательно, изменение URL), и действовать соответственно.
Хороший пример использования, описанный в официальном блоге реакции, называется " Рекомендация: полностью неконтролируемый компонент с ключом".
Таким образом, решение состоит в том, чтобы перейти от render() { return(<ul>
to render() { return(<ul key={this.props.location.pathname}>
Таким образом, всякий раз, когда местоположение изменяется в реагирующем маршрутизаторе, компонент удаляется (по реакции), и новое инициируется с правильными значениями (по реакции).
Да, и передайте location
качестве реквизита компоненту (Costumers
), где произойдет перенаправление, если оно еще не передано.
Надеюсь, это поможет кому-то.
Ответ 5
Для меня (реакции-маршрутизатор v4, реагируйте v16) проблема заключалась в том, что у меня был компонент навигации в порядке:
import { Link, withRouter } from 'react-router-dom'
class MainMenu extends Component {
render() {
return (
...
<NavLink to="/contact">Contact</NavLink>
...
);
}
}
export default withRouter(MainMenu);
Оба используют либо
to="/contact"
или же
OnClick={() => this.props.history.push('/contact')};
Поведение было таким же - URL в браузере изменился, но были отображены неправильные компоненты, маршрутизатор был вызван с тем же старым URL.
Виновник был в определении роутера. Мне пришлось переместить компонент MainMenu как дочерний компонент компонента Router!
// wrong placement of the component that calls the router
<MainMenu history={this.props.history} />
<Router>
<div>
// this is the right place for the component!
<MainMenu history={this.props.history} />
<Route path="/" exact component={MainPage} />
<Route path="/contact/" component={MainPage} />
</div>
</Router>
Ответ 6
Не используйте с маршрутизатором.
handleSubmit(e){
e.preventDefault();
this.props.form.validateFieldsAndScroll((err,values)=>{
if(!err){
this.setState({
visible:false
});
this.props.form.resetFields();
console.log(values.username);
const path = '/list/';
this.props.history.push(path);
}
})
}
Хорошо работает.
Ответ 7
Вам необходимо экспортировать клиентский компонент, а не CustomerList.
CustomersList = withRouter(Customers);
export default CustomersList;
Ответ 8
Вы можете получить доступ к свойствам объекта истории и ближайшему совпадению с помощью компонента высшего порядка withRouter. withRouter будет передавать обновленные соответствия, местоположение и историю в упакованный компонент всякий раз, когда он рендерится.
import React, { Component } from 'react'
import { withRouter } from 'react-router';
// you can also import "withRouter" from 'react-router-dom';
class Example extends Component {
render() {
const { match, location, history } = this.props
return (
<div>
<div>You are now at {location.pathname}</div>
<button onClick={() => history.push('/')}>{'Home'}</button>
</div>
)
}
}
export default withRouter(Example)
Ответ 9
Давай рассмотрим этот сценарий. У вас есть App.jsx
в качестве корневого файла для ReactJS SPA. В этом ваш render()
выглядит примерно так:
<Switch>
<Route path="/comp" component={MyComponent} />
</Switch>
тогда вы сможете без проблем использовать this.props.history
внутри MyComponent
. Допустим, вы визуализируете MySecondComponent
внутри MyComponent
, в этом случае вам нужно вызвать его следующим образом:
<MySecondComponent {...props} />
который передаст реквизит от MyComponent
до MySecondComponent
, тем самым сделав this.props.history
доступным в MySecondComponent
Ответ 10
Вам необходимо связать handleCustomerClick
:
class Customers extends Component {
constructor() {
super();
this.handleCustomerClick = this.handleCustomerClick(this)
}
Ответ 11
this.props.history.push('/customers/${customer.id}', null);