Примечание: я предполагаю, что у вас есть базовые знания о React и Redux, иначе эта статья вам не поможет
При запуске React я постоянно пытался выяснить, как лучше всего работать с API, пользовательским интерфейсом или базовой структурой проекта. Поработав некоторое время над этими вещами, я хотел поделиться лучшим подходом, который я нашел для себя (ваш пробег может быть другим).
В гипотетическом примере получения данных из API и отображения их в списке я бы сделал это так.
Шаг 1. Обработка запросов APIт.
1. API.js
Я начинаю с того, что сначала загружаю данные во внешний интерфейс. В любом компоненте я сохраняю файл api.js для обработки всех моих запросов для любого указанного компонента.
export const getParticipantList = url => { var participantList = api.Gget(url).then(response => { let metrics = { participantList: response.participant_lst, misc: response.misc }; return metrics; }); return participantList; };
В приведенном выше примере я использую Ajax для обработки API. У меня есть модуль API для обработки всех запросов в проекте, и с помощью «windows.export» я могу использовать «api.Gget» в любом месте проекта с импортом этой функции. Вы можете использовать fetch API или любую другую библиотеку для обработки запросов API.
2. сага.js
Redux Saga — это библиотека промежуточного программного обеспечения, используемая для обработки хранилища данных и асинхронных задач. Вы также можете использовать редукционные преобразователи в зависимости от ваших требований.
мы будем использовать saga для обработки нашей асинхронной задачи, то есть нашего вызова API.
import { call, put, takeLatest } from 'redux-saga/effects'; import { FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS, FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE, FETCH_DASHBOARD_PARTICIPANTS_LIST} from './constants'; import {getParticipantList} from './api' function* fetchParticipantList(action) { try { const data = yield call(getParticipantList,url); yield put({ type: FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS, data: data }) } catch (e) { yield put({ type: FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE, message: e.message }); } } function* participantSaga() { yield takeLatest(FETCH_DASHBOARD_PARTICIPANTS_LIST, fetchParticipantList); } export default participantSaga;
Saga работает с функциями генератора. Чтобы упростить понимание, рассмотрим два термина: слушатель и работник. Слушатель прослушивает каждое отправленное действие, чтобы оно соответствовало его типу. Если он поймает свой тип, он передаст рабочему процессу выполнение своего кода.
В нашем коде этим слушателем является participantSaga(). Он будет продолжать отслеживать, если тип: FETCH_DASHBOARD_PARTICIPANTS_LIST отправляется из действий. Если это так, он вызовет нашу рабочую функцию для ее выполнения. fetchParticipantList() в нашем случае является рабочим.
3. константы.js
В нашем компоненте нам может понадобиться много констант, которые необходимы в нескольких подкомпонентах. Я храню все константы в одном файле, чтобы облегчить себе работу.
export const FETCH_DASHBOARD_PARTICIPANTS_LIST="FETCH_DASHBOARD_PARTICIPANTS_LIST" export const FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS="FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS" export const FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE="FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE"
4. действия.js
при разговоре с редуктором мы отправляем определенные действия. которые помогают нам получить или изменить состояние глобального состояния.
export const fetchParticipantList = (params) =>{ return (dispatch) =>{ dispatch({ type: FETCH_DASHBOARD_PARTICIPANTS_LIST, action:params}) } }
Я обычно храню все свои действия в одном файле, чтобы сделать код более читабельным и модульным. В нашем примере мы отправим fetchParticipantList() из компонента, чтобы получить список участников. Мы также можем передавать аргументы в диспетчере в зависимости от наших потребностей.
5. редуктор.js
import { assign} from "lodash"; import{ FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE,FETCH_DASHBOARD_PARTICIPANTS_LIST,FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS } from './constants'; const initialState = { loading: false, errorMessage:'', participantList:[] } export default (state=initialState, action) => { const {type} = action; switch(type) { case FETCH_DASHBOARD_PARTICIPANTS_LIST: return assign({}, state, {loading: true}) case FETCH_DASHBOARD_PARTICIPANTS_LIST_SUCCESS: return assign({}, state, {misc:action.data.misc, participantList: action.data.participantList,loading: false}) case FETCH_DASHBOARD_PARTICIPANTS_LIST_FAILURE: return assign({}, state, {errorMessage: action.message}) default: return state; } }
Редьюсер действует как глобальное хранилище данных. Когда мы получаем данные с сервера, мы сохраняем их в редюсере, чтобы к ним могли обращаться несколько компонентов.
Шаг 2. Компонент
Теперь наша база для получения данных и их хранения готова, теперь нам нужно показать данные и вызвать вызов API при монтировании компонента. Я использую материальный пользовательский интерфейс, который содержит множество готовых компонентов, что упрощает создание современного веб-сайта. В нашем примере index.js будет содержать этот компонент. Мы создадим простое представление списка, содержащее все элементы нашего списка.
import React, { Component} from "react"; import Typography from "@material-ui/core/Typography"; import List from "@material-ui/core/List"; import ListItem from "@material-ui/core/ListItem"; import ListItemIcon from "@material-ui/core/ListItemIcon"; import ListItemText from "@material-ui/core/ListItemText"; const participants = props => { return ( <Grid item xs={12} md={12}> <div> <List dense={true}> {props.participantList.map((elem, id) => { return ( <ListItem> <ListItemIcon> <ListAltIcon /> </ListItemIcon> <ListItemText secondary={ <React.Fragment> {elem.name} <Typography variant="caption" display="block" gutterBottom > <strong>Filled on</strong>:{" "} {moment(elem.created_on).format("lll")} </Typography> <Typography variant="body2" gutterBottom> <strong>Value</strong>: {elem.id} </Typography> </React.Fragment> }></ListItemText> </ListItem> ); })} </List> </div> </Grid> ); }; const mapStateToProps = ({ participants}) => { const { participantList } = dashboardParticipants; return {participantList} export default connect(mapStateToProps)(participants);
ПРИМЕЧАНИЕ. В приведенном выше примере я использую как redux-thunk, так и redux-saga, поэтому мне не нужны mapDispatchToProps в компоненте.
Есть много способов сделать то, что я только что сделал, и некоторые из них могут быть даже лучше, но мы все учимся на наших усилиях и помогаем нашим сообществам. В следующей статье я покажу вам, как одновременно включить redux-saga и redux-thunk в наш проект.