Могу ли я вызвать API в componentWillMount в React?

Я работаю над реакцией за последний 1 год. Соглашение, которому мы следуем, это сделать вызов API в componentDidMount, получить данные и setState после того, как данные пришли. Это гарантирует, что компонент смонтирован и состояние установки вызовет повторную визуализацию компонента, но я хочу знать, почему мы не можем установить setState в componentWillMount или же constructor

Официальная документация гласит, что:

componentWillMount () вызывается непосредственно перед монтированием. Он вызывается перед render(), поэтому установка состояния в этом методе не вызовет повторную визуализацию. Избегайте введения каких-либо побочных эффектов или подписок в этом методе.

это говорит setting state in this method will not trigger a re-rendering, который я не хочу при вызове API. Если я могу получить данные и установить состояние (при условии, что вызовы API выполняются очень быстро) в componentWillMount или в constructor и данные присутствуют в первом рендере, зачем мне вообще рендеринг?

и если вызов API медленный, то setState будет асинхронным и componentWillMount уже вернулся, тогда я буду в состоянии setState и должен произойти повторный рендеринг.

В целом, я в значительной степени запутался, почему мы не должны делать вызовы API в конструкторе или componentWillMount. Может ли кто-нибудь действительно помочь мне понять, как реагирует в таком случае?

3 ответа

1. componentWillMount и повторный рендеринг

Сравните это два componentWillMount методы.
Один вызывает дополнительный повторный рендеринг, другой - нет

componentWillMount () {
  // This will not cause additional re-render
  this.setState({ name: 'Andrej '});
}

componentWillMount () {
  fetch('http://whatever/profile').then(() => {
    // This in the other hand will cause additional rerender,
    // since fetch is async and state is set after request completes.
    this.setState({ name: 'Andrej '});
  })
}

,
,
,
2. Где вызывать вызовы API?

componentWillMount () {
  // Is triggered on server and on client as well.
  // Server won't wait for completion though, nor will be able to trigger re-render
  // for client.
  fetch('...')
}

componentDidMount () {
  // Is triggered on client, but never on server.
  // This is a good place to invoke API calls.
  fetch('...')
} 

Если вы выполняете рендеринг на сервере, а вашему компоненту нужны данные для рендеринга, вам следует извлечь (и дождаться завершения) вне компонента, передать данные через реквизиты и впоследствии представить компонент в строку.

ComponentWillMount

Теперь, когда реквизит и состояние установлены, мы наконец вступаем в сферу методов жизненного цикла

Это означает, что React ожидает state быть доступным как render Затем будет вызвана функция, и код может прерваться, если отсутствует какая-либо упомянутая переменная состояния, что может произойти в случае ajax,


Конструктор

Это место, где вы определяете.

Поэтому вызов ajax не обновит значения любого состояния, поскольку ajax является асинхронным, и конструктор не будет ждать ответа. В идеале вы должны использовать конструктор для установки значений по умолчанию / начальных значений.


В идеале эти функции должны быть чисто функциями, только в зависимости от параметров. приведение ajax приносит побочный эффект, чтобы функционировать.

Да, функции зависят от state и используя this.setState может принести вам такие проблемы (вы установили значение в состоянии, но значение отсутствует в состоянии в следующей вызываемой функции).

Это делает код хрупким. Если ваш API действительно быстрый, вы можете передать это значение в качестве аргумента и в своем компоненте проверить, доступен ли этот аргумент. Если да, инициализируйте с ним. Если нет, установите его по умолчанию. Кроме того, в функции успеха Ajax, вы можете проверить ref этого компонента. Если он существует, компонент отображается и вы можете вызвать его state с помощью setState или любой setter(предпочтительная) функция.

Также помните, что когда вы говорите, что вызовы API действительно быстрые, ваш сервер и обработка могут выполняться с оптимальной скоростью, но вы никогда не можете быть уверены в сети.

Если вам нужны только данные при первом запуске, и если вы согласны с этим. Вы можете установить состояние синхронно с помощью обратного вызова.

например:

componentWillMount(){
    this.setState({
                sessionId: sessionId,                
            }, () => {
                if (this.state.hasMoreItems = true) {
                    this.loadItems()   // do what you like here synchronously 
                }
            });
}
Другие вопросы по тегам