Могу ли я вызвать 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('...')
}
Если вы выполняете рендеринг на сервере, а вашему компоненту нужны данные для рендеринга, вам следует извлечь (и дождаться завершения) вне компонента, передать данные через реквизиты и впоследствии представить компонент в строку.
Теперь, когда реквизит и состояние установлены, мы наконец вступаем в сферу методов жизненного цикла
Это означает, что 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
}
});
}