Как да направите AJAX заявки в React?

Ако аз избрах една тема, която се споменава много във форумите за React или фронтенд като цяло, това би било отправяне на AJAX заявка в React захранвани приложения.

Най-голямото объркване се корени във факта, че React често се рекламира като рамка и хората, запознати с рамки като AngularJS, се използват за извършване на разговори в API с неща като $ http и подобни библиотеки за помощници, предоставени от самия Angular. Не е така в React, тъй като React е „просто“ библиотека с изглед с някои методи за управление на състоянието и жизнения цикъл *.

И така - как да направите AJAX заявка, когато не е осигурена библиотека за вас?

Вие сте свободни да използвате всяка библиотека на трети страни! Можете да използвате вградената в браузъра реализация на извличането (може да искате да включите и whatwg-fetch polyfill за онези, останали с остарели браузъри) или да използвате axios. Аз лично предпочитам последния, тъй като axios има прост API и работи в повечето браузъри.

За да можете да използвате axios, всичко, което трябва да знаете, е как работят обещанията - ако някога сте използвали jQuery.ajax преди, трябва да сте готови да започнете.

Нека обясним използването въз основа на проста GET заявка:

axios.get ( "http://example.com/posts/1)
  .then (функция (отговор) {
    console.log (отговор);
  })

Изпращаме GET заявка до посочен URI и регистрираме отговора. Axios вече предполага, че отговорът ще бъде обект JSON за нас, така че не е необходимо да уточняваме допълнителни опции.

Както можете да видите, отправянето на AJAX заявка в React не е много по-различно от това да го направите с jQuery или AngularJS. Истинският въпрос е ...

Кога или къде да направите AJAX заявка?

Когато създавате структурата и работния си процес на приложението, ще трябва да вземете предвид как протичат данните във вашето приложение:

  • кой от компонентите трябва да може да изпрати заявка за получаване на нови данни?
  • как данните ще бъдат предадени на други компоненти?
  • ще има ли повече от едно действие, което може да доведе до извличане на данните (зареждане на подробности за публикациите на нейната страница, зареждане на подробности за публикациите в индексната страница, показване на подобни публикации)?

Има няколко „най-добри практики“ за решаване на въпроса къде да се обадя на AJAX заявките:

A - компонентDidMount

Вашият компонент - следвайки нашия пример - ще получи опора, съдържаща идентификатора или слугата на статията и ще направи заявката за зареждане на данните. Приложението ви може да изглежда така:

// App.js
render () {
  връщане (
    
              ); }
// BlogPost.js
компонентDidMount () {
  axios.get ( `http://exmaple.com/blog/$ {this.props.id}`)
    .then (отговор => this.setState (response.data))
}

В отговор на предаване на идентификатор като опора, компонентът ще изпрати AJAX заявка и след това в неговия метод render () ще провери дали данните са зададени в състояние - ако е така, ще визуализира съдържанието.

Въпреки че това може да изглежда като напълно валидно решение, всъщност се третира като анти-образец, тъй като сега сме промотирали компонента в контейнер и обвързваме презентационния елемент за неговото изпълнение, като по този начин намаляваме повторната му употреба.

Актуализация: В този раздел първоначално е посочено, че трябва да използвате компонент компонент WillMount, но всъщност не се препоръчва - всички операции, които причиняват странични ефекти, като аякс обаждания, трябва да се извършват в компонентDidMount, компонентDidUpdate.

Б - предаване на данни от родителски компонент чрез реквизит

Вместо да направим контейнер, ние ще предаваме всички данни директно като реквизит и ще зададем на нашия родителски компонент извличането на данните. Това се извършва най-вече в отговор на взаимодействието на потребителя под формата на промяна на URL адреса с реактор-рутер (бонус точки за използване на куката onEnter на маршрута).

Въпреки че тук използвам термина родителски компонент, все пак трябва да имате предвид забележката от точка А относно обвързването на компонента с неговото изпълнение. Трябва да се опитате да избягвате да имате твърде много контейнери / интелигентни компоненти в приложението си.

C - използване на мениджър на състояния като flux, redux или mobx

Голяма помощ за разбирането как данните трябва да / могат да протичат през вашето приложение е знанието за редукс или друга библиотека за управление на държавата (поток, mobx). Това е подобно на решението, описано в пример Б, но вместо да предаваме данните от родител на дете, ние ги държим в държавен мениджър, който се грижи за настройката на реквизита. Данните вече не се предават от компонент на компонент (не е необходимо ръчно да присвояваме реквизита - няма повече баба и дядо> родител> дете> вериги за внуци!), А вместо това се вземат директно от магазина (помислете за магазин като за глобално наличен единичен обект, съдържащ всички състояния и данни на приложението - това може да звучи страшно, но не забравяйте да прочетете документацията на дадена имплементация - опростявам нещата с цел да запазя това лесно за нови потребители).

Допълнителен бонус на това решение е фактът, че можем да се обадим на заявката AJAX от всяко място, което харесваме (в отговор на промяна на URL адреса, в компонентWillMount, като отговор на събитие от страна на сървъра, изпратено чрез сокет) и стига отговорът му да е предадени в магазина, нашите компоненти ще се актуализират съответно.

Приложение А - правейки го да изглежда гладко

Сега, когато знаем как да заредим данните от API, трябва да сме сигурни, че крайният потребител знае, че нещо се случва. За да направим това, можем малко да оправим метода си render ():

render () {
  ако (! this.props.title) {
    връщане <Зареждане />
  }
  връщане (
    <Статия>
      

{this.props.title}        ); }

Проверявайки дали ни бяха предадени всички реквизити, от които се нуждаем, можем да решим да покажем съдържанието на статията или трябва да информираме потребителя, че съдържанието все още се зарежда. Примерно изпълнение на такова решение:

Присмех към съдържанието, докато се зарежда

Сега, не изглежда ли много по-добре? Вижте публикацията, озаглавена „Деконструкция на запазване на съдържание във Facebook“, за да научите как Facebook се подиграва с публикацията, докато се зарежда. Разбира се, можете просто да поставите въртящо колело там, ако желаете :)

Приложение Б - примерно приложение

Примерно приложение за изпълнение на решението, описано в точка Б, и присмехуляването на публикации по време на предварително зареждане е достъпно на моя акаунт в github:

* въпреки че все още е опростяване, то е много по-близо до истината, отколкото да наричаме React рамка