Автор оригинала: Rowland Ekemezie.
Реагировать Экосистема стала огромной, так как Facebook сделала публику API. Более того, отличные библиотеки были построены в декларативном стиле, принятом реагированием.
Однако приложения Real Life требуют создания запросов AJAX на серверы. И это может представлять большую проблему при использовании реагирования. Вам нужно знать, какую библиотеку использовать для ваших процессов AJAX.
Приятно знать, что есть разные способы обрабатывать AJAX с реагированием. Это одна из красавиц реагирования как Просмотр библиотеки – Гибкость Отказ
Как сделать запрос AJAX с реагированием
- В пределах реакции.
- Делегата реле.
- Делегат redux.
1. В рамках компонента React
Это самый простой и самый распространенный подход для запросов AJAX. Здесь запрос AJAX выпускается непосредственно в ComponentDidmount Способ жизненного цикла вашего компонента. Вещи могут быть запутаны таким образом, когда ваша заявка растет.
Запрос на API GitHub для получения пользовательских деталей выглядит так:
// UserProfile Component class UserProfile extends React.Component { constructor() { super(); this.state = { user: [] } } // componentDidMount lifecycle method allows dynamic behaviour, AJAX, // side effects, etc. We issue our API call here and set the // response to component's state. componentDidMount() { gitHubApi('mentrie').then(data => { this.setState({ user: data }); }) } // Here, we destructure component's state and render the user details. render() { const { user } = this.state; return} } // Function that calls our specified endpoint on Github // We're using fetch method from fetch API to make the call. const gitHubApi = (username) => { return fetch(`https://api.github.com/users/${username}`) .then(response => { return response.json() .then(({ login, avatar_url, html_url }) => ({ login, avatar_url, html_url })); }) .catch(error => { throw error; }) }; // We mount the UserProfile component to the DOM ReactDOM.render(User details
, document.getElementById('root'));
Давайте проверим это здесь .
2. Делегационная реле
Реле Позволяет объявить требования к данным для ваших компонентов с GraphQL. И реле делает их доступными через реквизиты.
Реле элегантно для строительства крупных приложений – но у него есть некоторые накладные расходы. Это диапазоны от реле обучения и GraphQL для настройки серверов GraphQL.
Образец релейного потока может посмотреть это:
Источник: Facebook
3. Делегат Redux.
Redux Создан архитектуру потока для управления состоянием Action Application. С Redux вы перемещаете данные приложения и AJAX процессы от ваших компонентов.
С диаграммы вы можете увидеть, как состояние приложения и асинхронные процессы перемещаются в магазин.
Магазин это объект, который содержит полное состояние вашего приложения. Обратите внимание, что в Redux все состояния приложений хранятся как один объект. Единственный способ изменить его государство – это по Диспетчерские действия Отказ С этой реализацией вы поддерживаете один источник истины по вашему заявлению.
Редукторы Просто чистые функции, которые принимают предыдущее состояние и действие, затем возвращают следующее состояние. Это не мутата государства; Он делает копию предыдущего состояния, преобразует его и возвращает новое состояние в магазин. Затем магазин обновляет вид с новым состоянием, если есть изменения.
Редукторы, учитывая те же аргументы, должны рассчитать следующее состояние и вернуть его. Без сюрпризов. Нет побочных эффектов. Нет вызовов API. Нет мутаций. Редукторы синхронно и пассивные, таким образом, не идеальное место для асинхронизированных действий.
(previousState, action) => newState
Как тогда вы должны обрабатывать операции с побочными эффектами? Redux Async Библиотеки приходят к спасению:
Они Redux Hamberwares для обработки асинхронных задач и побочных эффектов в вашем приложении React/Redux.
Redux-Promise Использует стандартные действия потока и обещает привлечь четкие конвенции к асинкому вызовам. Это наименее популярное среди трех. Это функция промежуточного программного обеспечения, которая принимает обещание и отправляет разрешенное значение обещания. Он в основном возвращает обещание абоненту, чтобы он мог дождаться операции, чтобы закончить, прежде чем продолжить.
Redux-Thunk позволяет создавать действие для возврата функции вместо объекта действия. Таким образом, Действие Создатель становится Thunk Отказ
А Thunk
Это функция, которая создается, часто автоматически, чтобы помочь вызова друшему функции (E.g. API конечной точкой). А Thunk
обертывает асинхронную операцию в функции.
Когда Action Creator возвращает функцию, эта функция будет выполняться промежуточным программным обеспечением Thunk Redux. Эта функция не должна быть чистой; Таким образом, ему разрешается иметь побочные эффекты, в том числе выполнение асинхронных вызовов API или переход маршрутизатора. Функция также может отправлять действия.
Чтобы добавить Thunk Redux, мы используем absemiddleware ()
Если промежуточное программное обеспечение Redux Thunk включено, в любое время вы пытаетесь отправить функцию вместо объекта действия, промежуточное программное обеспечение позвонит этой функции с методом отправки в качестве первого аргумента.
Проверьте здесь как Дэн Абрамов Создатель Redux и Redux-Thunk дает подробное объяснение случаев использования.
Мы можем отправить как простые действия объекта, так и другие Teunks, которые позволяют нам составлять асинхронные действия в одном потоке.
// Dependencies const { applyMiddleware, createStore } = Redux; const { connect, Provider } = ReactRedux; // GitHub API const gitHubApi = (username) => { // Put your Api call here }; // redux-thunk implementation // source: https://github.com/gaearon/redux-thunk/blob/master/src/index.js // Redux-thunk handles most use cases for async actions in your application function thunkMiddleware(store) { return function(next) { return function(action) { if (typeof action === "function") { return action(store.dispatch, store.getState); } else { return next(action); } } } } // Action creator const getUserSuccess = (user) => { return { type: 'LOAD_USER_SUCCESS', user } } // User reducer implementation. // Simply returns the new user object to the store on LOAD_USER_SUCCESS. // Always remember to return state as the default case const userReducer = (state = {}, action) => { switch (action.type) { case 'LOAD_USER_SUCCESS': return action.user; default: return state; } }; // fetchUserDetails thunk // It returns a function that takes dispatch as the first argument. When AJAX // request is successful, it dispatches getUserSuccess action with user object. const fetchUserDetails = (username) => { return dispatch => { return gitHubApi(username) .then(user => { dispatch(getUserSuccess(user)) }).catch(error => { throw error; }) } } // React component class UserProfile extends React.Component { constructor() { super(); } // We call our thunk here. // componentDidmount is for dynamic behavior, side effects, AJAX, etc. componentDidMount() { this.props.fetchUserDetails('mentrie'); } render() { const { user } = this.props; return ( // Display the user value received from the store ) } } // Setup store const store = createStore(userReducer, applyMiddleware(thunkMiddleware)); // Map the store's state to component's props. // This way you keep the component in sync with redux store const mapStateToProps = (state) => ({ user: state }); // Wrap the thunk with dispatch method and // merge them to component's props const mapDispatchToProps = (dispatch) => ({ fetchUserDetails: (username) => dispatch(fetchUserDetails(username)) }); // Connect React component to redux store with react-redux connect() const UserProfilePage = connect( mapStateToProps, mapDispatchToProps)(UserProfile); // Mount the component to the DOM // Provider makes available the store's state to component's below // the hierarchy via connect() call. const element = document.getElementById('root'); ReactDOM.render(, element, 0 );
Redux-Thunk легко учиться с относительно небольшим API – всего десять линий кода. Но это может быть трудно проверить.
Давайте проверим это здесь .
Если вам все еще любопытно, см. Другой Async Action пример.
Redux-Saga Это промежуточное программное обеспечение Redux, которая устраняет сложность асинхронных процессов в вашем приложении React/Redux. Он использует силу ES6 Generators Сделать Async Tasks легко проверить, писать и причину.
Redux Saga управляет Async запрос и побочные эффекты более обработанным образом, чем для этого, чем для этого. Это уменьшает сложности в таких просьбах, делая Обратные вызовы, обещания, попробуйте/поймать блокирует только простые инструкции. Более того, это делает ваш код декларативным, более ополнен и читаемым. Тогда как вы могли бы использовать Redux-Thunk и Redux-Saga Вместе сага – это только то, чтобы вылечить ваши сложные боли рабочего процесса.
Когда ваш магазин должен обрабатывать сложные асинхронизированные операции, рассмотрите возможность использования Redux-Saga. Он обрабатывает асинхронные операции как простые инструкции. Redux-Saga элегантно управляет асинхронистыми задачами, сохраняя чистый редуктор.
А. Определите саги
// Here, we use ES6 destructuring assignment to extract payload // from the action object passed to it. function* loadUserDetails({ payload }) { try { const user = yield call(gitHubApi, payload); // Yields effect to the reducer specifying action type // and user details. yield put({type: 'LOAD_USER_SUCCESS', user}); } catch (error) { yield put({ type: 'LOAD_USER_FAILURE', error }); } } // Call loadUserDetails with action's payload each time // LOAD_USER_REQUEST is dispatched function* watchRequest() { yield* takeLatest('LOAD_USER_REQUEST', loadUserDetails); }
Сага являются генераторными функциями. Он использует генератор ES6. Проверьте статью Кайла Симпсона на Основы генератора ES6 Отказ
Генераторы – это функции, которые могут быть приостановлены и возобновлены. Из-за того, как работают генераторы, Redux-Saga способен делать сложные асинхронные рабочие процессы выглядеть синхронно.
У нас есть два сага, чтобы завершить эту операцию: Watchrequest
и LoadUserDetails
Отказ Сага оформлены на *
перед функцией.
API redux-Saga обнаруживает некоторые методы, которые нам нужно для завершения нашей задачи:
Позвоните
Это создатель эффекта, который запускает функцию с дополнительными параметрами. Он приостанавливает генератор, так как возвращаемый результат – это обещание. Генератор возобновляется, когда обещание разрешено или отклонено.Вилка
является создателем эффекта для создания неблокирующих вызовов на функцию.Takelatest
Отменяет любую текущую работу и вернуть результат последних действий, которые соответствуют его шаблону.возиться
Возвращает результат всех действий, которые соответствует его шаблону.поставить
Проще говоря/отправляет действия на указанный канал (объект, используемый для отправки и получения сообщений).
Проверьте Документация Для более методов.
Вернуться к нашему коду
- Takelatest Часы для
Load_user_request
Действия для отправки. - Затем он делает неблокирующий звонок в LoadUserDetails с возвращенным объектом действий. В этом случае тип действия и имени пользователя.
- Позвоните управляет Githubapi Функция с полезной нагрузкой (i.e имя пользователя) и разрешает значение, назначенное как Пользователь Отказ
- Теперь поставить рассылки
Load_user_success
С пользовательским значением обратно в магазин. - Наконец, если операция терпит неудачу, хорошая практика для отправки действия отказа, которое в нашем случае является
Load_user_failure
Отказ
B. Mount Sagas в магазине
// Create saga middleware const sagaMiddleware = createSagaMiddleware(); // Inject middleware to the store const store = createStore(userReducer, applyMiddleware(sagaMiddleware)); // Run the sagas you defined. // You would normally have a rootSaga were you register all your sagas // Or spread then in the run function. sagaMiddleware.run(watchRequest);
Чтобы сделать состояние и функции магазина доступны для компонента React, React-redux Библиотека предоставляет:
соединить Функция – соединяет реактивный компонент к магазину Redux.
Провайдер Компонент – компонент более высокого порядка, чтобы сделать магазин доступным для всех компонентов ниже иерархии, не передавая его прямо.
C. Подсоедините компонент React React для Store redux
// Dependencies const { applyMiddleware, createStore } = Redux; const createSagaMiddleware = ReduxSaga.default; const { put, call } = ReduxSaga.effects; const { takeLatest } = ReduxSaga; const { connect, Provider } = ReactRedux; // GitHub API const gitHubApi = (username) => { // Make API calls here }; // Action creator const getUserDetails = (payload) => { return { type: 'LOAD_USER_REQUEST', payload } } // Reducer const userReducer = (state = {}, action) => { switch (action.type) { case 'LOAD_USER_SUCCESS': return action.user; default: return state; } }; // Sagas goes here // UserProfile component class UserProfile extends React.Component { constructor() { super(); } componentDidMount() { this.props.getUserDetails('mentrie'); } render() { const { user } = this.props; return ( // Render user details here ) } } // Store setup goes here - - - - // Map the store's state to component's props. const mapStateToProps = (state) => ({ user: state }); // Wrap action creator with dispatch method. // This way getUserDetails is passed in as props. const mapDispatchToProps = (dispatch) => ({ getUserDetails: (username) => dispatch(getUserDetails(username)) }) // React-redux connect function links our React component to redux store const UserProfilePage = connect( mapStateToProps, mapDispatchToProps)(UserProfile); // Mount our component to the DOM const element = document.getElementById('root'); ReactDOM.render(, element, 0 );
Давайте проверим это здесь .
Обертывание
Операции AJAX в вашем приложении React лучше обрабатываются с библиотеками redux async. При использовании Redux, Не кладите AJAX в свои комментарии реагирования. Отделение беспокойства является ключом. Более того, если ваше приложение React/Redux требует совершения Async-операций, используйте Redux-Thunk или Redux-Saga, чтобы справиться с ней с Agility и элегантностью. Создание ASYNC запросов в ваших редукторах является анти-образцом и следует избегать.