React Context API: легкое управление состоянием

внешний интерфейс API React.js Redux

Оригинальная ссылка:React Context API: Managing State with Ease

Переводчик:OFED

Управлять состоянием очень просто благодаря новейшему React Context API. Следуйте за мной сейчас, чтобы узнать, чем он отличается от Redux и как он используется.

Обзор: React Context API не новинка в экосистеме React. Однако в Реакте16.3.0версия сделала некоторыеУлучшать. Эти улучшения настолько велики, что они значительно уменьшают нашу потребность в Redux и других расширенных библиотеках управления состоянием. В этой статье вы ознакомитесь с практическим руководством о том, как новый React Context API заменяет Redux для управления состоянием в небольших приложениях.

Краткий обзор REDUX

Перед этим давайте быстро взглянем на Redux, чтобы мы могли лучше сравнить разницу между ними.Redux — это библиотека JavaScript, которой легко управлять.. Сам Redux не имеет ничего общего с React. Многие разработчики со всего мира предпочитают использовать популярные интерфейсные фреймворки, такие какReactа такжеAngular) с помощью Redux.

Чтобы уточнить, в этой статье управление состоянием относится к обработке изменений состояния, вызванных определенными событиями в одностраничном приложении (SPA). Например, событие нажатия кнопки или асинхронное сообщение с сервера может инициировать изменение состояния приложения.

В Redux особенно нужно обратить внимание на следующие моменты:

  1. Состояние всего приложения хранится в одном объекте (называется источником данных).
  2. Если вы хотите изменить статус, вам нужно запустить метод Dispatch.actions, действия описывают, что должно произойти.
  3. В Redux вы не можете изменить свойства объекта или изменить существующий массив, вы всегда должны возвращать новый объект или новый массив.

Если вы новичок в Redux и хотите узнать больше, перейдите сюдаПрактическое руководство по ReduxУчить.

Руководство по контекстному API React

React Context API предоставляет способ передачи данных через дерево компонентов без необходимостиpropsАтрибуты передаются слой за слоем. В React данные обычно передаются от родительских к дочерним компонентам в виде свойства.

Для использования последней версии React Context API требуется три ключевых шага:

  1. передать начальное состояниеReact.createContext. Этот метод вернетProviderа такжеConsumerОбъект.
  2. использоватьProviderКомпоненты размещаются в верхней части дерева компонентов и получают свойство value. Атрибут value может быть любым значением.
  3. использоватьConsumerкомпоненты, в дереве компонентовProviderПодмножество состояния доступно в любом месте внутри компонента.

Как видите, задействованные концепции на самом деле не сильно отличаются от Redux. На самом деле, даже Redux использует React Context API под капотом своего общедоступного API. Однако только недавно Context API достиг достаточно зрелого уровня.

Создавайте приложения React с помощью Redux

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

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

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

Требования к проекту

Поскольку в этой статье используется только React и некоторые библиотеки NPM, вам не понадобится ничего, кроме Node.js и NPM. Если у вас не установлены Node.js и NPM, перейдите кОфициальный сайтЗагрузить и установить.

После установки этих зависимостей вам также необходимо установитьcreate-react-appинструмент. Этот инструмент помогает разработчикам создавать проекты React. Откройте терминал и выполните следующие команды для установки:

npm i -g create-react-app

Создайте React-приложение

установленыcreate-react-appПосле этого перейдите в каталог, где находится проект, и выполните следующую команду:

create-react-app redux-vs-context

Через несколько секундcreate-react-appСоздание приложения будет завершено. После этого перейдите в новый каталог, созданный инструментом, и установите Redux:

# 进入应用目录
cd redux-vs-context

# 安装 Redux
npm i --save redux react-redux

Уведомление: reduxосновная библиотека,react-redux— это библиотека, облегчающая взаимодействие между React и Redux. Короче говоря, последний действует как прокси между React и Redux.

Разрабатывайте приложения React с помощью Redux

Вы создали свое приложение React, установили Redux и теперь открываете свой проект в своем любимом инструменте разработчика. затем вsrcСоздайте в папке три файла:

  • foods.json: этот файл содержит статический массив, содержащий информацию о еде и ее происхождении.
  • reducers.js: этот файл используется для управления состоянием Redux в приложении.
  • actions.js: этот файл используется для сохранения методов в приложении, которые запускают изменения состояния Redux.

Итак, сначала откройтеfoods.jsonфайл, добавьте следующее:

[
  {
    "name": "Chinese Rice",
    "origin": "China",
    "continent": "Asia"
  },
  {
    "name": "Amala",
    "origin": "Nigeria",
    "continent": "Africa"
  },
  {
    "name": "Banku",
    "origin": "Ghana",
    "continent": "Africa"
  },
  {
    "name": "Pão de Queijo",
    "origin": "Brazil",
    "continent": "South America"
  },
  {
    "name": "Ewa Agoyin",
    "origin": "Nigeria",
    "continent": "Africa"
  }
]

Как видите, в данных, хранящихся в файле, нет ничего особенного. Просто набор разных продуктов из разных стран.

в определенииfoods.jsonИмея файлы на месте, вы можете сосредоточиться на создании своего магазина Redux. Подводя итог,storeявляется единственным источником истинного состояния вашего приложения. Откройте свойreducers.jsфайл, добавьте следующий код:

import Food from './foods';

const initialState = {
  food: Food,
  searchTerm: '',
};

export default function reducer(state = initialState, action) {
  // 根据 action type 区分
  switch (action.type) {
    case 'SEARCH_INPUT_CHANGED':
      const {searchTerm} = action.payload;
      return {
        ...state,
        searchTerm: searchTerm,
        food: searchTerm ? Food.filter(
          (food) => (food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1)
        ) : Food,
      };
    default:
      return state;
  }
}

В приведенном выше коде вы можете увидетьreducerМетод принимает два параметра:stateа такжеaction. Когда вы запускаете свое приложение React, этот метод получитinitialState, когда вы отправляете экземпляр действия, этот метод получит текущее состояние (больше неinitialState). Затем, исходя из содержания этих действий,reducerметод создаст новое состояние для вашего приложения.

Далее вам нужно определить, что делают эти действия. На самом деле, для простоты вы определите одно действие, которое запускается, когда пользователь вводит поисковый запрос в вашем приложении. Поэтому откройтеactions.jsфайл и вставьте в него следующий код:

function searchTermChanged(searchTerm) {
  return {
    type: 'SEARCH_INPUT_CHANGED',
    payload: {searchTerm},
  };
}

export default {
  searchTermChanged,
};

actionПосле создания следующее, что вам нужно сделать, это поместитьAppкомпоненты упакованы вreact-reduxкоторый предоставилProviderв компоненте. Поставщики несут единую ответственность за данные приложения React (т.е.store)передача.

Чтобы использовать provider , сначала вы будете использоватьreducers.jsопределено вinitialStateСоздайтеstore. Затем, поProviderкомпоненты, вы поставитеstoreперешел к вамApp. Для выполнения этих задач необходимо открытьindex.jsфайл и замените его содержимое на:

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import reducers from './reducers';
import App from './App';

// 使用 reducers 信息创建 store。
// 这是因为 reducers 是 Redux Store 的控制中心。
const store = createStore(reducers);

ReactDOM.render(
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById('root')
);

Вот и все! Вы только что настроили Redux в своем приложении React. Теперь вы должны реализовать пользовательский интерфейс (пользовательский интерфейс), чтобы ваши пользователи могли использовать функциональные возможности, реализованные в этом разделе.

Создайте интерфейс React

Теперь, когда вы завершили основной код своего приложения, вы можете сосредоточиться на создании пользовательского интерфейса. Для этого откройте свойApp.jsфайл, замените его содержимое следующим кодом:


import React from 'react';
import {connect} from 'react-redux';
import actions from './actions';
import './App.css';

function App({food, searchTerm, searchTermChanged}) {
  return (
    <div>
      <div className="search">
        <input
          type="text"
          name="search"
          placeholder="Search"
          value={searchTerm}
          onChange={e => searchTermChanged(e.target.value)}
        />
      </div>
      <table>
        <thead>
        <tr>
          <th>Name</th>
          <th>Origin</th>
          <th>Continent</th>
        </tr>
        </thead>
        <tbody>
        {food.map(theFood => (
          <tr key={theFood.name}>
            <td>{theFood.name}</td>
            <td>{theFood.origin}</td>
            <td>{theFood.continent}</td>
          </tr>
        ))}
        </tbody>
      </table>
    </div>
  );
}

export default connect(store => store, actions)(App);

Для людей, которые не использовали Redux, единственная вещь, с которой они не знакомы, — это инкапсуляция.Appкомпонентconnectметод. Этот метод на самом деле являетсяКомпоненты высшего порядка (HOC), действует как связующее звено между приложением и Redux.

Запустите свое приложение с помощью следующей команды, и вы сможете получить доступ к своему приложению в браузере:


npm run start

Однако, как вы можете видеть, приложение сейчас уродливое. Итак, чтобы сделать его немного лучше, вы можете открытьApp.cssфайл, замените его содержимое следующим:


table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 15px;
  line-height: 25px;
}

th {
  background-color: #eee;
}

td, th {
  text-align: center;
}

td:first-child {
  text-align: left;
}

input {
  min-width: 300px;
  border: 1px solid #999;
  border-radius: 2px;
  line-height: 25px;
}

Alt text

законченный! Теперь у вас есть базовое приложение React и Redux, и вы можете приступить к изучению того, как перейти на Context API.

Реализовать приложение с помощью React Context API

В этом разделе вы узнаете, как перенести ваше приложение Redux на React Context API.

К счастью, вам не нужно выполнять большой рефакторинг между Redux и Context API.

Во-первых, вы должны удалить компонент Redux из своего приложения. Для этого откройте терминал, удалитеreduxа такжеreact-reduxБиблиотеки:


npm rm redux react-redux

После этого удалите код ссылки на эти библиотеки в вашем приложении. ОткрытьApp.jsУдалите следующие строки:


import {connect} from 'react-redux';
import actions from './actions';

Затем в том же файле замените последнюю строку (начинающуюся с export default ) следующим кодом:


export default App;

Благодаря этим изменениям вы можете переписать свое приложение с помощью Context API.

Переход с Redux на React Context API

Чтобы преобразовать предыдущее приложение из приложения, управляемого Redux, для использования Context API, вам нужен контекст для хранения данных приложения (этот контекст заменит Redux Store). Кроме того, вам нуженContext.Providerкомпонент, который содержитstate,propsи нормальный жизненный цикл компонента React.

Для этого вам нужноsrcсоздать каталогproviders.jsфайл и добавьте в него следующий код:


import React from 'react';
import Food from './foods';

const DEFAULT_STATE = { allFood: Food, searchTerm: '' };

export const ThemeContext = React.createContext(DEFAULT_STATE);

export default class Provider extends React.Component {
  state = DEFAULT_STATE;
  searchTermChanged = searchTerm => {
    this.setState({searchTerm});
  };

  render() {
    return (
      <ThemeContext.Provider value={{
        ...this.state,
        searchTermChanged: this.searchTermChanged,
      }}> {this.props.children} </ThemeContext.Provider>);
  }
}

определено в приведенном выше кодеProviderКлассы отвечают за инкапсуляцию других компонентов вThemeContext.Providerсередина. Таким образом, вы можете получить доступ к этим компонентам, позволяющим приложениям изменять состояние состояния иsearchTermChangedметод.

Для использования этих значений в дереве компонентов необходимо создатьThemeContext.Consumerкомпоненты. Этому компоненту потребуется метод рендеринга, который получит вышеуказанноеpropsзначение в качестве параметра.

Итак, далее вам нужноsrcСоздайте каталог с именемconsumer.jsфайл и пишем в него следующий код:


import React from 'react';
import {ThemeContext} from './providers';

export default class Consumer extends React.Component {
  render() {
    const {children} = this.props;

    return (
      <ThemeContext.Consumer>
        {({allFood, searchTerm, searchTermChanged}) => {
          const food = searchTerm
            ? allFood.filter(
              food =>
                food.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1
            )
            : allFood;

          return React.Children.map(children, child =>
            React.cloneElement(child, {
              food,
              searchTerm,
              searchTermChanged,
            })
          );
        }}
      </ThemeContext.Consumer>
    );
  }
}

Теперь, чтобы завершить миграцию, вы откроетеindex.jsфайл, и вrender()функция, использованиеConsumerУпаковка компонентовAppкомпоненты. Кроме того, вам необходимоConsumerупаковано вProviderв компоненте. Код выглядит следующим образом:


import React from 'react';
import ReactDOM from 'react-dom';
import Provider from './providers';
import Consumer from './consumer';
import App from './App';

ReactDOM.render(
  <Provider>
    <Consumer>
      <App />
    </Consumer>
  </Provider>,
  document.getElementById('root')
);

Готово! Вы только что закончили переход с Redux на React Context API. Если вы запустите свое приложение сейчас, вы обнаружите, что все приложение работает как обычно. Единственная разница в том, что ваше приложение больше не использует Redux.

«Новый React Context API — отличная альтернатива Redux с точки зрения уменьшения размера приложения».

Не по теме: Сделайте ваше приложение React более безопасным с помощью Auth0

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

Суммировать

Редукс — этопередовойБиблиотека управления состоянием для использования при создании крупномасштабных приложений React. С другой стороны, Context API можно использовать в небольших приложениях React, где изменяются данные размером в байт. Используя Context API, вам не нужноreducers,actionsЕсли вы пишете много подобного кода, вы можете завершить отображение логики посредством изменения состояния.