#reactjs #react-router
#reactjs #react-маршрутизатор
Вопрос:
Я создаю веб-приложение react, используя react-router для навигации между страницами. Некоторые из этих страниц зависят от componentDidMount, запускаемого при переходе на страницу. Однако, похоже, это не запускается, пока я не обновлю страницу, которая кажется пользователям очень нелогичной.
Есть ли способ принудительно запустить componentDidMount, возможно, после завершения метода визуализации.
Извините, если это рассматривается как дублирующий вопрос, но ничто из того, что я видел, не помогло мне понять, как решить эту проблему.
componentDidMount = async () => {
//initialize web3
const web3 = await getWeb3();
// get contract address
const ethAddress = await storehash.options.address
this.setState({ethAddress})
//set account for Blockchain network
this.setState({account: await web3.eth.getAccounts()})
}
Комментарии:
1. Componentdidmount выполняется только один раз, при визуализации компонента. вы можете попробовать использовать другие жизненные циклы.
2. Также, если вы выполняете одну и ту же инициализацию для нескольких компонентов, вы могли бы переместить это в родительский и передать через props или переместить логику в компонент более высокого порядка
3. событие, которое вы ищете, я думаю,
componentWillReceiveProps
.. это будет вызываться каждый раз, когда компонент получает новый prop, и его необходимо повторно отобразить4. Я не отправляю никаких реквизитов на эту новую страницу, мне просто нужен способ запуска некоторого кода при загрузке этого нового маршрута
5. вы переходите по адресу, который соответствует одному и тому же
Route
, но имеет разные параметры, верно?
Ответ №1:
tl; dr — Только компоненты, отображаемые маршрутом (и их дочерние элементы), будут повторно отображаться при изменении маршрута.
Я собираюсь сделать несколько предположений. Во-первых, componentDidMount
вы пытаетесь использовать компонент, который не является дочерним для одного из ваших компонентов маршрута.
Второе предположение, которое я сделаю, заключается в том, что вам не нужно запускать, когда монтируется этот компонент, но когда монтируется один из компонентов новых маршрутов.
componentDidMount
Функция в компоненте, которая отображается с помощью маршрута, вероятно, там, где вам нужно быть. Однако, если вам нужно что-то обновить в состоянии этого компонента, когда монтируется один из его дочерних элементов, это не поможет. Однако вы можете сделать это несколькими различными способами.
Быстро и грязно Не берите в привычку делать это
Если вы просто что-то тестируете, быстрым и грязным методом является использование render
свойства маршрута вместо component
.
Так, например, если ваш маршрут выглядит следующим образом:
<Route path="/some-route" component={NewComponent} />
Вы могли бы изменить это (опять же… только для быстрого тестирования, не рекомендуется использовать это в любом производственном коде!)
<Route path="/some-route" render={(props) => {
//do your console log or temporary testing stuff here
return <NewComponent ...props />
}} />
Передайте функцию, которая передаст переменные от дочернего элемента
Менее грязным способом и предполагающим, что вы хотите, чтобы код имел доступ к чему-либо в этом родительском компоненте, было бы передать компоненту функцию. Опять же, вам пришлось бы использовать render
для этого:
someFunction = (passedVar) => {
// do something with passedVar, which you'll pass from the new component
}
// ... then in the Router...
<Route path="/some-route" render={(props) => <NewComponent ...props onRouteLoaded={this.someFunction} />}} />
Тогда у вас была бы функция ( this.props.onRouteLoaded(...)
), которую вы могли бы запускать на componentDidMount
из NewComponent
, НО НЕ на этом родительском компоненте. Это позволит вам передавать переменные родительскому компоненту, если вам нужно получить доступ к состоянию этого компонента, реквизитам и т.д.
Рекомендуется, если вам нужно это сделать
Гораздо более чистым способом сделать это было бы использовать Redux state для передачи значений, но (со всем уважением) разберитесь с жизненными циклами React, прежде чем нарушать Redux (но вы ДОЛЖНЫ нарушить Redux!)
Ответ №2:
Вы можете использовать componentDidUpdate
метод жизненного цикла для сравнения previous props
с current props
и повторного запуска логики снова; например
constructor(props) {
super(props);
this.componentLogic = this.componentLogic.bind(this);
}
componentLogic() {
// fetch something or some other business logic
}
componentDidMount() {
this.componentLogic();
}
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (
this.props.reactRouterDom.params.slug !==
prevProps.reactRouterDom.params.slug
) {
this.componentLogic();
}
}
Здесь я передаю route slug как prop через Higher Order Component(HOC)
и отслеживаю изменение маршрута через componentDidUpdate
жизненный цикл.