Как обращаться с промежуточным ПО с помощью Redux-Saga

Управление состоянием проекта из внешнего интерфейса может вызвать стресс, особенно если нет определенной логики. Redux-Saga упрощает задачу благодаря возможности тестирования.

Важнейшей задачей разработчика внешнего интерфейса является управление потоком данных от серверной части к интерфейсу. Это включает в себя управление текущим состоянием, совместное использование данных между компонентами и попытки не повторять процесс выборки одних и тех же данных дважды. Redux легко справится с этой задачей.

В этой статье мы больше сосредоточимся на управлении состоянием с помощью Redux и на том, как использовать Redux-Saga в качестве промежуточного программного обеспечения, чтобы упростить управление состоянием.

Вот что мы будем освещать в посте:

  • Введение в Редукс
  • Что такое промежуточное ПО?
  • Почему промежуточное ПО?
  • Введение в Redux-Saga
  • Как настроить Redux-Saga
  • Как использовать Redux-Saga с Redux
  • Saga Helper и создатель эффектов
  • Использование Saga в проекте React

Предпосылка

Чтобы следовать этому посту, вам необходимо иметь:

  • Узел установлен на вашем ПК
  • Базовое понимание React.
  • Базовое понимание Redux
  • Текстовый редактор

Введение в Редукс

Redux — это центральное хранилище данных для всех данных приложения. Это помогает любому компоненту приложения эффективно получать доступ к необходимым данным, что значительно упрощает управление состоянием.

App.js имеет две ветки: store и header.  Под магазином находятся категории и товары.  Под шапкой корзина и меню.  Магазин и корзина подключаются к центральному хранилищу данных Redux.

Изображение выше содержит представление простого потока приложения. Этот поток основан на компонентах. Давайте рассмотрим сценарий, в котором компонент магазина имеет все данные о продуктах, которые будут использоваться в приложении. Будет легко, если мы захотим передать данные компоненту категории или компоненту продуктов.

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

Это помогает, но становится еще более неприятным, когда имеешь дело с большим проектом, в котором у вас есть много компонентов, передающих свойства. Этот подход может быть не таким эффективным, особенно если вы смотрите с точки зрения оптимизации — любые изменения в любом компоненте вызовут обновление во всех компонентах со связанными с ним реквизитами. Это влияет на время загрузки пользователей.

Способ эффективно решить эту проблему — использовать среду управления состоянием — здесь на помощь приходит Redux. Как было определено ранее, Redux — это центральное хранилище, в котором хранятся данные, доступные любому компоненту приложения.

Что такое промежуточное ПО?

Промежуточное программное обеспечение в Redux — это способ расширения пользовательской функциональности; это дает дополнительные возможности существующему Redux. Он предоставляет стороннее расширение с точками между отправкой действия и моментом, когда оно достигает редуктора. Промежуточное ПО также можно использовать для отчетов о сбоях, ведения журналов, асинхронного выполнения задачи и т. д.

Почему ПО промежуточного слоя?

Мы используем энхансеры, чтобы переопределить функцию отправки для Redux, но иногда мы заинтересованы в настройке функции отправки. Redux использует промежуточное ПО для настройки функций диспетчеризации. Некоторые другие библиотеки, такие как Express, также используют промежуточное программное обеспечение для настройки определенного поведения в приложении.

Введение в Redux-Saga

Redux-Saga — это сопутствующая библиотека для Redux, которая эффективно управляет асинхронным потоком приложения. Это позволяет хранилищу Redux асинхронно взаимодействовать с ресурсами за пределами хранилища, включая доступ к локальному хранилищу, HTTP-запросы и выполнение служб ввода и вывода, которые эффективно управляются.

Redux-Saga — пример промежуточного программного обеспечения Redux; другие типы включают Redux Thunk и т. д.

Начиная

Мы создадим базовое приложение, которое может получать список пользователей из API, и мы будем управлять состоянием с помощью Redux и Redux-Saga. Введите приведенную ниже команду в терминал, чтобы создать проект React.

npx create-react-app users

Эта команда создаст пустой шаблон приложения create-react-app. Откройте файл проекта в предпочитаемом вами текстовом редакторе.

Давайте установим все необходимые зависимости: react-redux, redux, redux-saga и bootstrap. Используйте команду ниже, чтобы установить их.

yarn add react-redux redux redux-saga boostrap

Откройте корневую папку и создайте папку с именем redux. Внутри создайте две подпапки с именами «actions» и «reducers». Наконец, создайте файл с именем store.js и добавьте в него следующий код.

import { createStore } from "redux";
import rootReducer from "./reducers";

const store = createStore(rootReducer);
export default store;

В приведенном выше коде мы импортируем createStore из Redux, чтобы создать хранилище Redux, и мы импортируем rootReducer, который содержит все редукторы, которые у нас будут в проекте.

Далее мы создали переменную и присвоили ей хранилище, которое будем создавать. Теперь давайте создадим наши редукторы. Во-первых, внутри редукторов папки создайте файл index.js и файл users.js; редуктор, который мы будем использовать в проекте, будет связан с файлом index.js, а файл users.js будет содержать пользовательский редьюсер. Вставьте следующий код в файл index.js:

import { combineReducers } from "redux";

const rootReducer = combineReducers({
 //All reducers will be here
});
export default rootReducer

Мы используем combReducers, чтобы объединить все редьюсеры в одно место, которым является rootReducer. Мы добавим редукторы внутрь позже.

Теперь давайте поработаем над нашим пользовательским редюсером. Добавьте следующий код в файл user.js:

import * as types from '../types';

const initialState = {
 users: []
}

export default function users(state=initialState, action) {
 switch (action.type) {
  case type.GET_USERS;
   return {
    ...state,
    users: action.payload;
   }
  default: 
   return state;
 }
}

В приведенном выше коде мы импортируем типы, которые создадим позже, а затем устанавливаем для InitialState состояние хранилища по умолчанию; это то, что мы будем передавать редюсеру пользователей. Каждый редьюсер в Redux принимает два параметра: начальное состояние и действие. Редуктор использует переключатель для проверки типа действия, которое будет использоваться для определения возвращаемого значения.

Теперь мы добавим редьюсер к созданному ранее rootReducer. Давайте воспользуемся приведенным ниже кодом для обновления файла index.js редукторов:

import { combineReducers } from "redux";
import Users from "./users";
const rootReducer = combineReducers({
  users: Users,
})
export default rootReducer;

Давайте создадим наши типы, создадим файл types.js внутри папки redux и добавим в файл следующий код:

export const GET_USERS = "GET_USERS";

Теперь давайте создадим действия для наших редюсеров. Создайте файл users.js в папке действий и добавьте в файл следующий код.

import * as types from "../types"

export function getUsers(users) {
 return {
  type: type.GET_USERS(),
  payload: users,
 }
}

Наконец, давайте добавим поставщика в файл index.js в корневой папке. Обновите файл index.js с помощью приведенного ниже кода:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
 <Provider store={store}>
  <React.StrictMode>
   <App />
  </React.StrictMode>
 </Provider>,
 document.getElementById('root')
);

Мы добавляем Provider в качестве оболочки, чтобы покрыть весь проект; это позволяет обмениваться данными в рамках нашего проекта. Провайдер принимает созданное нами хранилище, содержащее данные, которые мы храним.

Внутри компонента карточки добавим следующий код.

import React from 'react'
const Card = ({user}) => {
  return (
    <div className="card">
      <div className="card-body">
        <div className="card-title">{user.name}</div>
        <div className="card-subtitle mb-2 text-muted">{user.company.name}</div>
        <div className="card-text">{user.company.catchPhrase}</div>
      </div>
    </div>
  )
}
export default Card

Внутри компонента мы получаем пользовательские данные в качестве реквизита и отображаем их на основе имени пользователя, компании и ключевой фразы компании. Затем добавьте следующий код в компонент Users.

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { getUser } from '../redux/actions/users'
import Card from "./Card"
const Users = () => {
  const dispatch = useDispatch()
  const users = useSelector(state => state.users.users)

  useEffect(() => {
    dispatch(getUser([{
     id: 1, 
     name: "Emmanuel",
     company: "Dusk",
     catchPhrase: "Made to fly"
    }]));
  }, [dispatch])
  return (
    <>
      {
        users.length > 0 && users.map(user => (
          <Card user={user} key={user.id} /> 
        ))
      }
      { users.length === 0 ? <p>No users</p> : null }
    </>
  )
}
export default Users

 

В приведенном выше коде мы импортируем useDispatch и useSelector. useDispatch возвращает ссылку на отправку из созданного нами хранилища, а useSelector позволяет нам извлекать данные из хранилища.

Мы используем useSelector для получения данных о пользователях из хранилища. Напротив, мы используем метод useEffect для временной установки данных пользователей с помощью функции диспетчеризации, в ожидании времени, когда мы добавим промежуточное программное обеспечение. Мы перебираем данные пользователей, чтобы передать данные каждого пользователя компоненту карты.

Давайте обновим файл app.css с помощью этого стиля, чтобы придать ему нужный эффект.

.App {
 margin: 5%;
}
.card {
 margin: 10px;
}

Теперь давайте добавим redux dev, чтобы через него можно было управлять состоянием. Сначала откройте store.js и обновите его с помощью приведенного ниже кода.

import { createStore, compose } from 'redux';
import rootReducer from './reducers/index';
const store = compose(
  applyMiddleware(sagaMiddleware),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )(createStore)(rootReducer);
export default store;

Теперь давайте настроим наше промежуточное ПО. Создайте вложенную папку в папке src с именем saga и добавьте в нее файлы index.js и userSaga.js.

Начнем с файла userSaga.js — добавьте в него следующий код:

import { call, put, takeEvery } from 'redux-saga/effects';
const apiUrl = 'https://jsonplaceholder.typicode.com/users';
function getApiData() {
 return fetch(apiUrl).then(response => response.json().catch(error => error));
}

function* fetchUsers(action) {
 try {
  const users = yield call(getApiData);
  yield put({ type: 'GET_USERS_SUCCESS', users: users });
 } catch (error) {
  yield put({ type: 'GET_USERS_FAILED', message: error.message });
 }
}

function* userSaga() {
 yield takeEvery('GET_USERS_REQUESTED', fetchUsers);
}

export default userSaga;

Запуск побочного эффекта Redux-Saga осуществляется через процесс создания декларативных эффектов. Redux-Saga всегда будет комбинировать эти эффекты вместе, чтобы заставить работать поток управления. Использование таких эффектов, как call и put, с помощью takeEvery достигает той же цели, что и Redux Thunk, то есть служит промежуточным программным обеспечением с тестируемостью в качестве дополнительного преимущества.

В приведенном выше коде мы импортируем put, call и takeEvery из Redux-Saga. Мы будем использовать их, чтобы получить функциональность нашего промежуточного программного обеспечения. Поэтому мы создали переменную apiUrl для хранения URL-ссылки для API, а также создали функцию getApiData, которая извлекает пользовательские данные из конечной точки API.

Затем приступаем к созданию генератора саги. Генератор fetchUsers получает параметр действий и использует метод try-catch. Метод try использует эффект вызова для получения getApiData. Затем, используя эффект размещения, он устанавливает тип и действие функции отправки на основе функции отправки.

Затем мы создаем генератор userSaga, который берет генератор fetchUsers и использует эффект takeEvery, чтобы преобразовать его в тип GET_USER_REQUESTED.

Наконец, давайте добавим этот код в файл index.js в подпапке saga.

import { all } from "redux-saga/effects";
import userSaga from "./userSaga";
export default function* rootSaga() {
 yield all([userSaga()]);
}

В приведенном выше коде мы импортируем все из redux-saga/effects и импортируем userSaga из файла userSaga, который мы создали ранее. Мы создали генератор, который выдает userSaga в магазин, используя эффект all.

Нам нужно будет внести некоторые изменения в наш предыдущий код. Откройте store.js и обновите его с помощью приведенного ниже кода.

import { createStore, compose, applyMiddleware } from 'redux';
import rootReducer from './reducers/index';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './saga/index';
const sagaMiddleware = createSagaMiddleware();
const store = compose(
  applyMiddleware(sagaMiddleware),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )(createStore)(rootReducer);
  sagaMiddleware.run(rootSaga);
export default store;

Приведенные выше изменения устанавливают Redux-Saga, которую мы создавали, в качестве промежуточного программного обеспечения. Затем откройте файл types.js и обновите его с помощью приведенного ниже кода.

export const GET_USERS_REQUESTED = 'GET_USERS_REQUESTED';
export const GET_USERS_SUCCESS = 'GET_USERS_SUCCESS';
export const GET_USERS_FAILED = 'GET_USERS_FAILED';

Теперь откройте папку редукторов и обновите файл users.js следующим кодом.

import * as type from "../types";
const initalState = {
  users: [],
  loading: false,
  error: null
}
export default function users(state = initalState, action) {
  switch (action.type) {
    case type.GET_USERS_REQUESTED:
      return {
        ...state,
        loading: true
      }
    case type.GET_USERS_SUCCESS:
      return {
        ...state,
        loading: false,
        users: action.users
      }
    case type.GET_USERS_FAILED:
      return {
        ...state,
        loading: false,
        error: action.message
      }
    default:
      return state;
  }
}

В приведенном выше коде мы обновили начальное состояние и добавили в него созданные нами действия и промежуточное ПО. Перейдите к компоненту User и обновите его следующим кодом.

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { getUser } from '../redux/actions/users'
import Card from "./Card"
const Users = () => {
  const dispatch = useDispatch()
  const users = useSelector(state => state.users.users)
  const loading = useSelector(state => state.users.loading)
  const error = useSelector(state => state.users.error)
  useEffect(() => {
    dispatch(getUser());
  }, [dispatch])
  return (
    <>
      {
        users.length > 0 && users.map(user => (
          <Card user={user} key={user.id} /> 
        ))
      }
      { users.length === 0 ? <p>No users</p> : null }
      { users.length === 0 && loading === true ? <p>Loading...</p> : null }
      { error === 0 && !loading === true ? <p>{error.message}</p> : null }
    </>
  )
}
export default Users

Наконец, добавьте это обновление в файл users.js в папке действий.

import * as types from "../types";
export function getUser(users) {
  return {
    type: types.GET_USERS_REQUESTED,
    payload: users,
  }
}

Теперь все сделано идеально. Откройте терминал и запустите проект, используя следующую команду.

yarn start
//or

npm start

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

список карточек с именем человека, компанией и слоганом

Вывод

В этом посте мы узнали о Redux, промежуточном ПО, почему и где использовать промежуточное ПО и Redux-Saga. Все это мы продемонстрировали на простом проекте; вы можете легко воспроизвести это для больших проектов, чтобы легко управлять состоянием.

Ссылка: https://www.telerik.com/blogs/handling-middleware-redux-saga

#react #redux #reduxsaga

What is GEEK

Buddha Community

Как обращаться с промежуточным ПО с помощью Redux-Saga

Как обращаться с промежуточным ПО с помощью Redux-Saga

Управление состоянием проекта из внешнего интерфейса может вызвать стресс, особенно если нет определенной логики. Redux-Saga упрощает задачу благодаря возможности тестирования.

Важнейшей задачей разработчика внешнего интерфейса является управление потоком данных от серверной части к интерфейсу. Это включает в себя управление текущим состоянием, совместное использование данных между компонентами и попытки не повторять процесс выборки одних и тех же данных дважды. Redux легко справится с этой задачей.

В этой статье мы больше сосредоточимся на управлении состоянием с помощью Redux и на том, как использовать Redux-Saga в качестве промежуточного программного обеспечения, чтобы упростить управление состоянием.

Вот что мы будем освещать в посте:

  • Введение в Редукс
  • Что такое промежуточное ПО?
  • Почему промежуточное ПО?
  • Введение в Redux-Saga
  • Как настроить Redux-Saga
  • Как использовать Redux-Saga с Redux
  • Saga Helper и создатель эффектов
  • Использование Saga в проекте React

Предпосылка

Чтобы следовать этому посту, вам необходимо иметь:

  • Узел установлен на вашем ПК
  • Базовое понимание React.
  • Базовое понимание Redux
  • Текстовый редактор

Введение в Редукс

Redux — это центральное хранилище данных для всех данных приложения. Это помогает любому компоненту приложения эффективно получать доступ к необходимым данным, что значительно упрощает управление состоянием.

App.js имеет две ветки: store и header.  Под магазином находятся категории и товары.  Под шапкой корзина и меню.  Магазин и корзина подключаются к центральному хранилищу данных Redux.

Изображение выше содержит представление простого потока приложения. Этот поток основан на компонентах. Давайте рассмотрим сценарий, в котором компонент магазина имеет все данные о продуктах, которые будут использоваться в приложении. Будет легко, если мы захотим передать данные компоненту категории или компоненту продуктов.

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

Это помогает, но становится еще более неприятным, когда имеешь дело с большим проектом, в котором у вас есть много компонентов, передающих свойства. Этот подход может быть не таким эффективным, особенно если вы смотрите с точки зрения оптимизации — любые изменения в любом компоненте вызовут обновление во всех компонентах со связанными с ним реквизитами. Это влияет на время загрузки пользователей.

Способ эффективно решить эту проблему — использовать среду управления состоянием — здесь на помощь приходит Redux. Как было определено ранее, Redux — это центральное хранилище, в котором хранятся данные, доступные любому компоненту приложения.

Что такое промежуточное ПО?

Промежуточное программное обеспечение в Redux — это способ расширения пользовательской функциональности; это дает дополнительные возможности существующему Redux. Он предоставляет стороннее расширение с точками между отправкой действия и моментом, когда оно достигает редуктора. Промежуточное ПО также можно использовать для отчетов о сбоях, ведения журналов, асинхронного выполнения задачи и т. д.

Почему ПО промежуточного слоя?

Мы используем энхансеры, чтобы переопределить функцию отправки для Redux, но иногда мы заинтересованы в настройке функции отправки. Redux использует промежуточное ПО для настройки функций диспетчеризации. Некоторые другие библиотеки, такие как Express, также используют промежуточное программное обеспечение для настройки определенного поведения в приложении.

Введение в Redux-Saga

Redux-Saga — это сопутствующая библиотека для Redux, которая эффективно управляет асинхронным потоком приложения. Это позволяет хранилищу Redux асинхронно взаимодействовать с ресурсами за пределами хранилища, включая доступ к локальному хранилищу, HTTP-запросы и выполнение служб ввода и вывода, которые эффективно управляются.

Redux-Saga — пример промежуточного программного обеспечения Redux; другие типы включают Redux Thunk и т. д.

Начиная

Мы создадим базовое приложение, которое может получать список пользователей из API, и мы будем управлять состоянием с помощью Redux и Redux-Saga. Введите приведенную ниже команду в терминал, чтобы создать проект React.

npx create-react-app users

Эта команда создаст пустой шаблон приложения create-react-app. Откройте файл проекта в предпочитаемом вами текстовом редакторе.

Давайте установим все необходимые зависимости: react-redux, redux, redux-saga и bootstrap. Используйте команду ниже, чтобы установить их.

yarn add react-redux redux redux-saga boostrap

Откройте корневую папку и создайте папку с именем redux. Внутри создайте две подпапки с именами «actions» и «reducers». Наконец, создайте файл с именем store.js и добавьте в него следующий код.

import { createStore } from "redux";
import rootReducer from "./reducers";

const store = createStore(rootReducer);
export default store;

В приведенном выше коде мы импортируем createStore из Redux, чтобы создать хранилище Redux, и мы импортируем rootReducer, который содержит все редукторы, которые у нас будут в проекте.

Далее мы создали переменную и присвоили ей хранилище, которое будем создавать. Теперь давайте создадим наши редукторы. Во-первых, внутри редукторов папки создайте файл index.js и файл users.js; редуктор, который мы будем использовать в проекте, будет связан с файлом index.js, а файл users.js будет содержать пользовательский редьюсер. Вставьте следующий код в файл index.js:

import { combineReducers } from "redux";

const rootReducer = combineReducers({
 //All reducers will be here
});
export default rootReducer

Мы используем combReducers, чтобы объединить все редьюсеры в одно место, которым является rootReducer. Мы добавим редукторы внутрь позже.

Теперь давайте поработаем над нашим пользовательским редюсером. Добавьте следующий код в файл user.js:

import * as types from '../types';

const initialState = {
 users: []
}

export default function users(state=initialState, action) {
 switch (action.type) {
  case type.GET_USERS;
   return {
    ...state,
    users: action.payload;
   }
  default: 
   return state;
 }
}

В приведенном выше коде мы импортируем типы, которые создадим позже, а затем устанавливаем для InitialState состояние хранилища по умолчанию; это то, что мы будем передавать редюсеру пользователей. Каждый редьюсер в Redux принимает два параметра: начальное состояние и действие. Редуктор использует переключатель для проверки типа действия, которое будет использоваться для определения возвращаемого значения.

Теперь мы добавим редьюсер к созданному ранее rootReducer. Давайте воспользуемся приведенным ниже кодом для обновления файла index.js редукторов:

import { combineReducers } from "redux";
import Users from "./users";
const rootReducer = combineReducers({
  users: Users,
})
export default rootReducer;

Давайте создадим наши типы, создадим файл types.js внутри папки redux и добавим в файл следующий код:

export const GET_USERS = "GET_USERS";

Теперь давайте создадим действия для наших редюсеров. Создайте файл users.js в папке действий и добавьте в файл следующий код.

import * as types from "../types"

export function getUsers(users) {
 return {
  type: type.GET_USERS(),
  payload: users,
 }
}

Наконец, давайте добавим поставщика в файл index.js в корневой папке. Обновите файл index.js с помощью приведенного ниже кода:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
 <Provider store={store}>
  <React.StrictMode>
   <App />
  </React.StrictMode>
 </Provider>,
 document.getElementById('root')
);

Мы добавляем Provider в качестве оболочки, чтобы покрыть весь проект; это позволяет обмениваться данными в рамках нашего проекта. Провайдер принимает созданное нами хранилище, содержащее данные, которые мы храним.

Внутри компонента карточки добавим следующий код.

import React from 'react'
const Card = ({user}) => {
  return (
    <div className="card">
      <div className="card-body">
        <div className="card-title">{user.name}</div>
        <div className="card-subtitle mb-2 text-muted">{user.company.name}</div>
        <div className="card-text">{user.company.catchPhrase}</div>
      </div>
    </div>
  )
}
export default Card

Внутри компонента мы получаем пользовательские данные в качестве реквизита и отображаем их на основе имени пользователя, компании и ключевой фразы компании. Затем добавьте следующий код в компонент Users.

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { getUser } from '../redux/actions/users'
import Card from "./Card"
const Users = () => {
  const dispatch = useDispatch()
  const users = useSelector(state => state.users.users)

  useEffect(() => {
    dispatch(getUser([{
     id: 1, 
     name: "Emmanuel",
     company: "Dusk",
     catchPhrase: "Made to fly"
    }]));
  }, [dispatch])
  return (
    <>
      {
        users.length > 0 && users.map(user => (
          <Card user={user} key={user.id} /> 
        ))
      }
      { users.length === 0 ? <p>No users</p> : null }
    </>
  )
}
export default Users

 

В приведенном выше коде мы импортируем useDispatch и useSelector. useDispatch возвращает ссылку на отправку из созданного нами хранилища, а useSelector позволяет нам извлекать данные из хранилища.

Мы используем useSelector для получения данных о пользователях из хранилища. Напротив, мы используем метод useEffect для временной установки данных пользователей с помощью функции диспетчеризации, в ожидании времени, когда мы добавим промежуточное программное обеспечение. Мы перебираем данные пользователей, чтобы передать данные каждого пользователя компоненту карты.

Давайте обновим файл app.css с помощью этого стиля, чтобы придать ему нужный эффект.

.App {
 margin: 5%;
}
.card {
 margin: 10px;
}

Теперь давайте добавим redux dev, чтобы через него можно было управлять состоянием. Сначала откройте store.js и обновите его с помощью приведенного ниже кода.

import { createStore, compose } from 'redux';
import rootReducer from './reducers/index';
const store = compose(
  applyMiddleware(sagaMiddleware),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )(createStore)(rootReducer);
export default store;

Теперь давайте настроим наше промежуточное ПО. Создайте вложенную папку в папке src с именем saga и добавьте в нее файлы index.js и userSaga.js.

Начнем с файла userSaga.js — добавьте в него следующий код:

import { call, put, takeEvery } from 'redux-saga/effects';
const apiUrl = 'https://jsonplaceholder.typicode.com/users';
function getApiData() {
 return fetch(apiUrl).then(response => response.json().catch(error => error));
}

function* fetchUsers(action) {
 try {
  const users = yield call(getApiData);
  yield put({ type: 'GET_USERS_SUCCESS', users: users });
 } catch (error) {
  yield put({ type: 'GET_USERS_FAILED', message: error.message });
 }
}

function* userSaga() {
 yield takeEvery('GET_USERS_REQUESTED', fetchUsers);
}

export default userSaga;

Запуск побочного эффекта Redux-Saga осуществляется через процесс создания декларативных эффектов. Redux-Saga всегда будет комбинировать эти эффекты вместе, чтобы заставить работать поток управления. Использование таких эффектов, как call и put, с помощью takeEvery достигает той же цели, что и Redux Thunk, то есть служит промежуточным программным обеспечением с тестируемостью в качестве дополнительного преимущества.

В приведенном выше коде мы импортируем put, call и takeEvery из Redux-Saga. Мы будем использовать их, чтобы получить функциональность нашего промежуточного программного обеспечения. Поэтому мы создали переменную apiUrl для хранения URL-ссылки для API, а также создали функцию getApiData, которая извлекает пользовательские данные из конечной точки API.

Затем приступаем к созданию генератора саги. Генератор fetchUsers получает параметр действий и использует метод try-catch. Метод try использует эффект вызова для получения getApiData. Затем, используя эффект размещения, он устанавливает тип и действие функции отправки на основе функции отправки.

Затем мы создаем генератор userSaga, который берет генератор fetchUsers и использует эффект takeEvery, чтобы преобразовать его в тип GET_USER_REQUESTED.

Наконец, давайте добавим этот код в файл index.js в подпапке saga.

import { all } from "redux-saga/effects";
import userSaga from "./userSaga";
export default function* rootSaga() {
 yield all([userSaga()]);
}

В приведенном выше коде мы импортируем все из redux-saga/effects и импортируем userSaga из файла userSaga, который мы создали ранее. Мы создали генератор, который выдает userSaga в магазин, используя эффект all.

Нам нужно будет внести некоторые изменения в наш предыдущий код. Откройте store.js и обновите его с помощью приведенного ниже кода.

import { createStore, compose, applyMiddleware } from 'redux';
import rootReducer from './reducers/index';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './saga/index';
const sagaMiddleware = createSagaMiddleware();
const store = compose(
  applyMiddleware(sagaMiddleware),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )(createStore)(rootReducer);
  sagaMiddleware.run(rootSaga);
export default store;

Приведенные выше изменения устанавливают Redux-Saga, которую мы создавали, в качестве промежуточного программного обеспечения. Затем откройте файл types.js и обновите его с помощью приведенного ниже кода.

export const GET_USERS_REQUESTED = 'GET_USERS_REQUESTED';
export const GET_USERS_SUCCESS = 'GET_USERS_SUCCESS';
export const GET_USERS_FAILED = 'GET_USERS_FAILED';

Теперь откройте папку редукторов и обновите файл users.js следующим кодом.

import * as type from "../types";
const initalState = {
  users: [],
  loading: false,
  error: null
}
export default function users(state = initalState, action) {
  switch (action.type) {
    case type.GET_USERS_REQUESTED:
      return {
        ...state,
        loading: true
      }
    case type.GET_USERS_SUCCESS:
      return {
        ...state,
        loading: false,
        users: action.users
      }
    case type.GET_USERS_FAILED:
      return {
        ...state,
        loading: false,
        error: action.message
      }
    default:
      return state;
  }
}

В приведенном выше коде мы обновили начальное состояние и добавили в него созданные нами действия и промежуточное ПО. Перейдите к компоненту User и обновите его следующим кодом.

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { getUser } from '../redux/actions/users'
import Card from "./Card"
const Users = () => {
  const dispatch = useDispatch()
  const users = useSelector(state => state.users.users)
  const loading = useSelector(state => state.users.loading)
  const error = useSelector(state => state.users.error)
  useEffect(() => {
    dispatch(getUser());
  }, [dispatch])
  return (
    <>
      {
        users.length > 0 && users.map(user => (
          <Card user={user} key={user.id} /> 
        ))
      }
      { users.length === 0 ? <p>No users</p> : null }
      { users.length === 0 && loading === true ? <p>Loading...</p> : null }
      { error === 0 && !loading === true ? <p>{error.message}</p> : null }
    </>
  )
}
export default Users

Наконец, добавьте это обновление в файл users.js в папке действий.

import * as types from "../types";
export function getUser(users) {
  return {
    type: types.GET_USERS_REQUESTED,
    payload: users,
  }
}

Теперь все сделано идеально. Откройте терминал и запустите проект, используя следующую команду.

yarn start
//or

npm start

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

список карточек с именем человека, компанией и слоганом

Вывод

В этом посте мы узнали о Redux, промежуточном ПО, почему и где использовать промежуточное ПО и Redux-Saga. Все это мы продемонстрировали на простом проекте; вы можете легко воспроизвести это для больших проектов, чтобы легко управлять состоянием.

Ссылка: https://www.telerik.com/blogs/handling-middleware-redux-saga

#react #redux #reduxsaga

Sidney  Purdy

Sidney Purdy

1592305339

Channels in Redux-saga

What are the channels? Are they useful to us in day to day programming? We’ll be going through this blog that channels are played really a major role in redux-saga.

Channels:
Channels are of 3 types which are used to perform 3 different things, here I will brief you about those channels here but will explain in detail a bit later.

  • Action Channels: Action channel is a buffer, it stockpiles actions which sagas can consume one by one.
  • Generic Channels: Generally, we use Generic channels to communicate between two sagas. This can be done through the Actions but the idea of a channel is that communication is limited interest in sagas without other sagas being privy to that information.
  • Event Channels: Event Channel is completely different used to wrap outside event sources. we can consider web socket as a good example of the Event channel.

#react #redux #saga #redux-saga

Terry  Tremblay

Terry Tremblay

1599736380

How to implement Redux Saga with ReactJS and Redux?

Intro to Redux setup tutorial

Very often, you can hear about the state in frontend applications, but what it exactly is? Let me explain.

State in frontend applications represents all the data stored in the application in a given time. It can be stored in different formats like objects or strings. Based on the state’s values, we can personalize the application, display, and hide certain elements.

To manage the state in modern frontend frameworks, we can use different libraries like Redux, MobX, or NgRx. The most common one is Redux, which is used mainly with ReactJS applications, although it’s possible to use it with Angular as well.

With Redux, the state of the application is kept in the store, and we can access the store from every component in the application. Redux consist of store, reducers, and actions.

In this article, I’d like to tell you more about the Redux library and create a simple ReactJS project, where I’ll set up a Redux step by step.

Let’s start!

How does Redux work?

Redux is based on the flux architecture, and it supports unidirectional data flow. It means that data in the application goes through the same lifecycle over and over again, which makes everything that happens in the state more predictable.

Let’s take a look at the simple graphic, which illustrates the data’s lifecycle in the Redux application.

Image for post

On the graphic above, you can see that from the UI, we trigger an action that passes the data to the reducer. Next, the reducer updates the store, which is the state of our application. The store defines the user interface.

Let’s think of the benefits which using Redux can bring to our development.

Benefits of using Redux

When you’re building the application, you know more or less how much data you will need to manage inside the application. In most cases, frontend applications have some functionality, and very rare they are just static websites. Commonly, we keep some user data, forms data, etc. inside the application state, and then it’s very useful to use a tool for managing the state.

The most popular solution in ReactJS applications is Redux. There are some important benefits to the popularity of this solution. Let’s take a look at them one by one.

  • predictable state — The state in Redux is predictable because reducer functions are pure; therefore, if we pass the same state and the same action, it needs to return the same result. Redux state is also immutable; it can’t be changed or modified.
  • easy to maintain — Considering that it’s predictable and very strict about the structure of the Redux application, anyone who knows Redux will understand it and work with it easily.
  • easy to debug — Redux allows us to log the behavior using available developer tools, makes debugging easier.
  • developer tools available — Redux has amazing developer tools, that can be used in the browser to see what’s happens in the backend.
  • server-side rendering — Redux supports server-side rendering by allowing to manage initial rendering. Redux sends the state of the application to the server with a response to the server’s request.

Above I listed a few benefits of using Redux to manage the state of your frontend application. Now, I’d like to go to the practical part, where we are going to set up a Redux with ReactJS application.

#javascript #react #redux-saga #frontend #redux

Effie  Predovic

Effie Predovic

1627774860

Handle Multiple Sagas with Call & All Effect in Redux Saga

In this video, I am going to explain that how you can handle multiple sagas with the help of call and all effect in Redux Saga.

#redux #redux saga.

Felicita  Kunde

Felicita Kunde

1589794440

React Boilerplates with Redux, Redux Saga and Best Practices

Learn about redux and redux saga.

Youtube channel: IPenywis - https://www.youtube.com/watch?v=9CYcRj-zwk0

#react #redux #redux saga