Как установить react redux
Перейти к содержимому

Как установить react redux

  • автор:

Installation

Redux Toolkit includes the Redux core, as well as other key packages we feel are essential for building Redux applications (such as Redux Thunk and Reselect).

It’s available as a package on NPM for use with a module bundler or in a Node application:

# NPM npm install @reduxjs/toolkit  # Yarn yarn add @reduxjs/toolkit 

It’s also available as a UMD build, which can be loaded from the dist folder on unpkg. The UMD builds make Redux Toolkit available as a window.RTK global variable.

Complementary Packages​

React-Redux​

npm install react-redux 

Note that unlike Redux itself, many packages in the Redux ecosystem don’t provide UMD builds, so we recommend using module bundlers like Vite and Webpack for the most comfortable development experience.

Redux DevTools Extension​

Redux Toolkit’s configureStore automatically sets up integration with the Redux DevTools. You’ll want to install the browser extensions to view the store state and actions:

  • Redux DevTools Extension:
    • Redux DevTools Extension for Chrome
    • Redux DevTools Extension for Firefox

    If you’re using React, you’ll want the React DevTools extension as well:

    • React DevTools Extension:
      • React DevTools Extension for Chrome
      • React DevTools Extension for Firefox

      Create a React Redux App​

      The recommended way to start new apps with React and Redux is by using our official Redux+TS template for Vite, or by creating a new Next.js project using Next’s with-redux template.

      Both of these already have Redux Toolkit and React-Redux configured appropriately for that build tool, and come with a small example app that demonstrates how to use several of Redux Toolkit’s features.

      # Vite with our Redux+TS template # (using the `degit` tool to clone and extract the template) npx degit reduxjs/redux-templates/packages/vite-template-redux my-app  # Next.js using the `with-redux` template npx create-next-app --example with-redux my-app 

      We do not currently have official React Native templates, but recommend these templates for standard React Native and for Expo:

      • https://github.com/rahsheen/react-native-template-redux-typescript
      • https://github.com/rahsheen/expo-template-redux-typescript

      Redux Core​

      To install the redux core package by itself:

      # NPM npm install redux  # Yarn yarn add redux 

      If you’re not using a bundler, you can access these files on unpkg, download them, or point your package manager to them.

      Оглавление

      image

      image

      Вот вы прочитали мою статью про React (если нет, то настоятельно рекомендую вам сделать это) и начали разрабатывать приложения на нём. Но что это? Вы замечаете, как с расширением вашего приложения становится всё сложнее следить за текущим состоянием, сложно следить за тем, когда и какие компоненты рендарятся, когда они не рендарятся и почему они не рендарятся, сложно следить за потоком изменяющихся данных. Для этого и есть библиотека Redux. Сам React хоть и лёгкий, но для комфортной разработки на нем нужно много чего изучить.

      И сегодня мы разберём 2 библиотеки: Redux и React-redux. Для использования Redux’а вам не нужно скачивать дополнительных библиотек, но, если использовать его в связке с библиотекой React-redux разработка становится ещё удобнее и проще.

      Все примеры из этой статьи вы можете найти в этом репозитории на Github. Там находится полностью настроенное приложение React с использованием Redux и React-redux. Вы можете использовать его как начальную точку для вашего проекта. Изменяйте названия файлов и добавляйте новые в этот репозитории для создания собственного приложения. Смотрите во вкладку релизы для того что бы найти разные версии приложения. Первая содержит приложение только с использованием Redux, второе с использованием Redux и React-redux.

      Мотивация использования Redux

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

      Redux является универсальным средством разработки и может быть использован в связке с различными библиотеками и фреймворками. В этой же статье будет рассматривается использование Redux в React приложениях.

      1. Установка Redux и начало работы

      Используете ли вы Yarn или Npm, выполните одну из этих команд для установки Redux:

      # NPM npm install redux # Yarn yarn add redux 

      Скорее всего вы используете папку src в которой хранится ваша кодовая база. Файлы, связанные с redux принято хранить в отдельной папке. Для этого я использую папку /src/store в которой хранится всё то, что связано с Redux и хранилищем приложения. Вы можете назвать ее по другому или поместить в другое место.

      Создайте базовую структуру для хранилища. Она должна выглядит примерно следующим образом:

      .store
      ├── actionCreators
      │ ├── action_1.js
      │ └── action_2.js
      ├── actions
      │ ├── action_1.js
      │ └── action_2.js
      ├── reducers
      │ ├── reducer_1.js
      │ ├── reducer_2.js
      │ └── rootReducer.js
      ├── initialState.js
      └── store.js

      Конечно здесь я использовал примитивные названия для файлов, это сделано для наглядности. В настоящем проекте так называть файлы не стоит.

      2. Redux

      2.1 createStore

      Когда вы создали базовую структуру для работы с хранилищем Redux пришло время понять то как вы можете взаимодействовать с ним.

      Глобальное хранилище приложения создаётся в отдельном файле, который как правило называется store.js:

      // Код файла store.js import < createStore >from 'redux'; const store = createStore(reducer); export default store;

      2.2 reducer()

      reducer — чистая функция которая будет отвечать за обновление состояния. Здесь реализовывается логика в соответствие с которой будет происходить обновление полей store.

      Так выглядит базовая функция reducer:

      function reducer(state, action) < switch(action.type) < case ACTION_1: return < value: action.value_1 >; case ACTION_2: return < value: action.value_2 >; default: return state; > >

      Функция принимает значение текущего состояния и обьект события (action). Обьект события содержит два свойства — это тип события (action.type) и значение события (action.value).

      К примеру если нужно обработать событие onChange для поля ввода то объект события может выглядеть так:

      Некоторые события могут не нуждаться в передаче каких-либо значении. К примеру, обрабатывая событие onClick мы можем сигнализировать о том, что событие произошло, более никаких данных не требуется, а как на него реагировать будет описывать логика, заложенная непосредственно в сам компонент которой должен на него реагировать и частично в reducer. Но во всех случаях необходимо определять тип события. Редьюсер как бы спрашивает: что произошло? actio.type равен «ACTION_1» ага значит произошло событие номер 1. Дальше его нужно как то обработать и обновить состояние. То, что вернёт редьюсер и будет новым состоянием.

      ACTION_1 и ACTION_2 это константы событий. По-другому Actions. Про них мы поговорим далее 2.5 Actions.

      Как вы уже догадались store может хранить сложную структуру данных состоящих из набора независимых свойств. Обновление одного свойства оставит нетронутым другие свойства. Так из примера выше, когда происходит событие номер один (ACTION_1) обновляется поле номер один (value_1) в store при этом поле номер два (value_2) остаётся нетронутым. В общем механизм схож с методом this.setState().

      2.3 dispatch()

      Что бы обновить store необходимо вызвать метод dispatch(). Он вызывается у объекта store который вы создаёте в store.js. Этот объект принято называть store поэтому обновление состояния в моём случае выглядит так:

      store.dispatch(< type: ACTION_1, value_1: "Some text" >);

      ACTION_1 это константа события о которой речь пойдет дальше (см. Actions).

      Эта функция вызовет функцию reducer который обработает событие и обновит соответствующие поля хранилища.

      2.4 actionCreator()

      На самом деле передавать объект события напрямую в dispatch() является признаком плохого тона. Для этого нужно использовать функцию под названием actionCreator. Она делает ровно то что и ожидается. Создаёт событие! Вызов этой функции нужно передавать как аргумент в dispatch а в actionCreator передавать необходимое значение (value). Базовый actionCreator выглядит следующим образом:

      function action_1(value) < return < type: ACTION_1, value_1: value >; > export default action_1;

      Таким образом вызов dispatch должен выглядеть так:

      store.dispatch(action_1("Some value"));

      С использованием actionCreator код становится более чистым.

      2.5 Actions

      actions это константы, описывающие событие. Обычно это просто строка с названием описывающее событие. К примеру константа описывающее событие номер один будет выглядеть следующем образом:

      const ACTION_1 = "ACTION_1"; export default ACTION_1;

      Опять же в проекте вам стоит называть константы в соответствии с событием, которое она описывает: onClick, createUserSesion, deleteItem, addItem и т.д. Главное, чтобы было понятно. Замете что я нигде не писал import поэтому не забудьте импортировать ваши константы перед их использованием. Потому что константы тоже принято разбивать на отдельные файлы храня их в специальной папке. Хотя некоторые хранят их в одном файле под названием actionTypes.js. Такое решение нельзя назвать не правильным, но и не идеальным.

      2.6 getState()

      С помощью dispatch() обновили, а как теперь посмотреть новое значение store? Ничего изобретать не нужно, есть метод getState(). Он также, как и метод dispatch вызывается на экземпляре объекта store. Поэтому для моего примера вызов

      store.getState()

      вернёт значение полей хранилища. К примеру что бы посмотреть значение поля value_1 необходимо будет вызвать

      store.getState().value_1

      2.7 subscribe()

      А как же узнать, когда состояние обновилось? Для этого есть метод subscribe(). Он также вызывается на экземпляре store. Данный метод принимает функцию, которая будет вызывается каждый раз после обновления store. Он как бы «подписывает» функцию, переданную ему на обновление. К примеру следующий код при каждом обновлении (при каждом вызове dispatch()) будет выводить новое значение store в консоль.

      store.subscribe(() => console.info(store.getState()))

      Этот метод возвращает функцию unsubscribe(). Которая позволяет «отписаться от обновления». К примеру если компонент удаляется из DOM стоит отписать его методы от обновления в componentWillUnmount(). Этот метод жизненного цикла вызывается при размонтировании компонента и это именно то место где стоит отписываться от обновления. Проще говоря в деструкторе.

      2.8 combineReducers()

      combineReducers() позволяет объединить несколько редьюсеров в один.

      Если логика обновления компонентов довольно сложна и\или необходимо обрабатывать большое количество различных типов событий, то корневой reducer может стать слишком громоздким. Лучшим решением будет разбить его на несколько отдельных редьюсеров каждый из которых отвечает за обработку только одного типа событий и обновления определённого поля.

      Когда вы разбиваете базовый редьюсер на несколько, то название каждого из них должно соответствовать полю которое он обновляет в store.

      К примеру если редьюсер обновляет поле номер один, то он может выглядеть так:

      function value_1(state, action) < switch(action.type) < case ACTION_1: return action.value_1; default: return state; >> export default value_1;

      Название редьюсера (value_1) показывает какое свойство он будет обновлять в store. Если переименуете его в value_2 то он станет обновлять value_2. Поэтому учтите это!

      Когда используется единый редьюсер мы показываем какое поле хотим обновить:

       case ACTION_1: return < value_1: action.value_1 >;

      Но когда вы разделили ваши редьюсеры вам нужно просто вернуть новое значение:

      case ACTION_1: return action.value_1;

      Поскольку здесь не требуется указывать которое из полей обновляет редьюсер ибо его название и есть поле которое он обновляет.

      2.9 initialState

      initialState — объект, представляющий начальное состояние хранилища. Он является вторым не обязательным аргументом метода createStore(). С созданием хранилища можно сразу объявить начальное состояние для его полей. Этот объект желательно создавать, даже в тех случаях, когда объявления начального состояния не требуется. Потому что этот объект помогает посмотреть на структуру хранилища и название его полей. Обычный объект initialState выглядит следующим образом:

      const initialState = < date_1: "value. ", date_2: "value. " >; export default initialState;

      В некоторых случаях (когда компонент сразу использует значение из store), его объявление может стать обязательным иначе вы получите ошибку: TypeError: Cannot read property ‘value_1’ of undefined.

      Также редьюсеры всегда должны возвращать по дефолту текущее состояние. К примеру, если используется единый reducer то последнее значение в switch должно выглядеть так:

      default: return store;

      Если же вы разделяете редьюсеры на независимые функции, то он должен возвращать значение того свойства за которое он отвечает:

      default: return store.value_1;

      Также если вы не передаёте объект initialState в createStore вы можете вернуть его из редьюсера. В обоих случаях будет инициализировано начальное состояние для store.

      3. React-redux

      Казалось бы, у нас есть всё что бы использовать Redux. Но на деле использование его без пакета React-redux в React приложениях выглядит не очень красиво.

      3.1 Provider

      Для использование store в компоненте вам необходимо передавать его в пропсы:

      ReactDOM.render( />, document.getElementById('root'));

      И после использовать в компоненте: this.props.state. Для этого react-redux предостовляет метод Provider:

      ReactDOM.render( > , document.getElementById('root'));

      Таким образом метод connect сможет использовать store. В противном случае вы получите ошибку: Error: Could not find «store» in the context of «Connect(Main)». Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(Main) in connect options.

      Также можно передать store напрямую в компонент, не оборачивая его в Provider и это будет работать. Но лучше всё-таки используйте Provider.

      3.2 mapStateToProps()

      Этот метод вызывается всякий раз, когда происходит обновление store и именно он передаёт необходимые свойства из store в компонент. К примеру компонент, должен реагировать и обновлять UI каждый раз, когда поле номер один (value_1) обновилось. На обновление других полей ему реагировать не нужно. Если вы не используете React-redux вам бы пришлось использовать метод subscribe() что бы узнавать об обновлении и далее каким то образом проверять обновилось ли поле номер один или нет. В общем несложно понять, что такой код будет выглядеть слишком грязным и избыточным. С помощью mapStateToProps() можно чётко определить какие поля интересуют компонент. И на какие поля он должен реагировать.

      Возвращаясь к примеру выше, если компоненту один нужно получать поле номер один (value_1) то mapStateToProps для него будет выглядеть следующим образом:

      function (state) < return < value_1: state.value_1 >; >

      После внутри компонента мы можем обращается к полю value_1 через this.props.value_1. И каждый раз когда это поле будет обновляется компонент будет рендерится заново.

      Вы можете создать отдельную папку в /src/store для хранения файлов каждый из которых будет содержать функцию mapStateToProps для всех ваших компонентов. Либо (как сделал это я) использовать единую функцию возвращающую функцию mapStateToProps для каждого компонента. Лично мне нравится такой подход. Такая функция выглядит следующим образом:

      function mapStateToProps(component) < switch(component) < case "Component_1": < return function (state) < return < value_1: state.value_1 >; > > case "Component_2": < return function(state) < return < value_2: state.value_2 >; > > default: return undefined; > > export default mapStateToProps;

      Эта функция в качестве аргумента принимает строку с названием компонента и возвращает функцию mapStateToProps которая возвращает объект со свойством из store необходимом для данного компонента. Эту функцию можно назвать mapStateToPropsGenerator().

      3.3 mapDispatchToProps()

      Эта функция передаёт в компонент методы для обновления необходимого поля store. Что бы не вызывать dispatch напрямую из компонента вы будете использовать данный метод для того что бы передавать в props метод вызов которого приведёт к вызову dispatch и обновлению соответствующего поля. Просто теперь это будет выглядеть более элегантно, а код более понятным и чистым.

      К примеру компонент, номер один должен иметь возможность обновлять поле номер один из store. Тогда mapDispatchToProps для него будет выглядеть следующим образом:

      function (dispatch) < return < changeValue_1: bindActionCreators(action_1, dispatch) >; >;

      Теперь для обновления свойства value_1 вы будете вызывать changeValue_1() через this.props.changeValue_1(value). Не вызывая dispatch напрямую через this.props.store.dispatch(action_1(value)).

      bindActionCreators следует импортировать из redux. Он позволяет оборачивать функцию dispatch и actionCreator в единый объект. Вы можете не использовать bindActionCreators но тогда код будет выглядеть избыточным. Вы должны старятся реализовать какую-либо функциональность так, чтобы код выгладил просто и миниатюрно. Поэтому ничего лишнего писать не следует.

      Только чистый и понятный код. Метод bindActionCreators(actionCreator, dispatch) принимает два обязательных параметра это функцию actionCreator о которой мы уже говорили и dispatch. Возвращая метод для изменения полей store.

      Также как и для mapStateToProps я использую функцию генератор возвращающую функцию mapDispatchToProps для каждого компонента:

      import < bindActionCreators >from 'redux'; import action_1 from './actionCreators/action_1'; import action_2 from './actionCreators/action_2'; function mapDispatchToProps(component) < switch(component) < case "Component_1": return function(dispatch) < return < change_value_1: bindActionCreators(action_1, dispatch) >; >; case "Component_2": return function(dispatch) < return < change_value_2: bindActionCreators(action_2, dispatch) >; >; default: return undefined; > > export default mapDispatchToProps;

      3.4 connect()

      Ну и теперь кульминация! То без чего всё это не будет работать. Это функция connect.
      Именно она связывает mapStateToProps и mapDispatchToProps с компонентом и передает необходимые поля и методы в него. Возвращает она новый компонент-обёртку для вашего компонента. Как правильно именовать такой компонент я не знаю, ибо в самой документации React-redux это не описывается. Лично я добавляю окончание _w для компонентов оберток. Как бы _w = wrap Component. Подключение компонента в этм случае выглядит так:

      const COMPONENT_1_W = connect(mapStateToProps("Component_1"), mapDispatchToProps("Component_1"))(Component_1);

      И теперь в ReactDOM.render() вы передаёте не ваш компонент, а тот что возвращает функция connect.

      Если же у компонента нет необходимости в передаче ему mapStateToProps или mapDispatchToProps передавайте undefined или null в него.

      Урок #2 — Установка Redux

      Урок #2 - Установка Redux

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

      Видеоурок

      Полезные ссылки:

        Скачать папку со всеми материалами ;

      Официальный сайт NodeJS ;
      Инструкция по установке WebPack .

      Для запуска Redux необходимо скачать готовую папку с файлами. В папке прописан файл «package.json», что содержит все необходимые зависимости для корректной работы проекта.

      Чтобы установить все зависимости пропишите команду npm install , а для запуска веб сервера пропишите команду npm run start .

      Подключение Redux Toolkit к React — React: Redux Toolkit

      Теперь перейдем к Redux Toolkit и соберем простое приложение с двумя кнопками, меняющими значение счетчика. Это позволит увидеть основные концепции Redux Toolkit.

      Для интеграции нам понадобятся два пакета — react-redux и сам Toolkit, который поставляется в пакете @reduxjs/toolkit :

      # Выполните в корне проекта npm install @reduxjs/toolkit react-redux 

      Далее мы начнем собирать пазл, но сначала посмотрим на структуру директорий, от которой будем отталкиваться. Такая структура наиболее простая, но не единственная возможная:

      Для работы с Toolkit мы выделили директорию slices и внутри два файла: index.js и counterSlice.js.

      В файле index.js мы будем инициализировать хранилище и объединять все редьюсеры. Сами же редьюсеры разбиваются по отдельным файлам, их называют слайсы или срезы. Каждый слайс отвечает за определенную сущность в приложении. Например, если в вашем приложении есть список товаров и покупателей, то логично выделить два слайса: один — для товаров, другой — для покупателей.

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

      // file: slices/counterSlice.js import  createSlice > from '@reduxjs/toolkit'; // Начальное значение const initialState =  value: 0, >; const counterSlice = createSlice( name: 'counter', initialState, // Редьюсеры в слайсах мутируют состояние и ничего не возвращают наружу reducers:  increment: (state) =>  state.value += 1; >, decrement: (state) =>  state.value -= 1; >, // Пример с данными incrementByAmount: (state, action) =>  state.value += action.payload; >, >, >); // Слайс генерирует действия, которые экспортируются отдельно // Действия генерируются автоматически из имен ключей редьюсеров export const  increment, decrement, incrementByAmount > = counterSlice.actions; // По умолчанию экспортируется редьюсер, сгенерированный слайсом export default counterSlice.reducer; 

      Для создания редьюсера, мы создаем начальное значение initialState и вызываем createSlice() , который выполняет всю работу. Эта функция принимает объект. В этом объекте сейчас нам важны только три свойства:

      • name — задает имя слайса
      • initialState — задает начальное состояние
      • reducers — принимает объект, в котором каждое свойство содержит редьюсеры, с помощью которых мы будем менять состояние

      Вызов createSlice() вернет готовый слайс — это объект, в котором сейчас нам важны только два свойства:

      • actions — это экшены, с помощью которых мы запускаем созданные редьюсеры. Названия экшенов будет совпадать с ключами, которые мы указали в reducers при создании слайса. Нам не нужно самим создавать экшены и придумывать строковые имена их типам — всё за нас делает Toolkit. В примере выше мы экспортируем объект с экшенами, которые получили из этого свойства, дальше мы можем импортировать экшены в компонентах, чтобы вызывать действия
      • reducer — это готовый редьюсер, который мы будем подключать в стор. В примере выше он импортируется по умолчанию просто для удобства, чтобы разграничить экспорт экшенов и редьюсера

      Теперь редьюсер готов к использованию. Сначала мы должны его подключить в общий стор. Для этого передаем редьюсер в функцию configureStore() . Эта функция умеет комбинировать редьюсеры самостоятельно, в отличие от такой же функции в Redux. Функция принимает на вход объект с ключом reducer , значением которого становится объект с редьюсерами. У общего состояния state ключи будут такими же, как у этого объекта. Более подробно мы это разберем чуть позже.

      Так выглядит создание стора:

      // file: slices/index.js import  configureStore > from '@reduxjs/toolkit'; import counterReducer from './counterSlice.js'; export default configureStore( reducer:  // Свойство counter будет внутри объекта общего состояния: state.counter counter: counterReducer, >, >); 

      Здесь мы вызываем функцию configureStore() и передаем в нее объект со свойством reducer . А вот уже в reducer мы указываем объект с нашими редьюсерами. В нашем примере есть единственный редьюсер counterReducer , который мы импортируем по умолчанию из counterSlice.js.

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

      // file: slices/index.js import  configureStore > from '@reduxjs/toolkit'; import usersReducer from './usersReducer.js'; import tasksReducer from './tasksReducer.js'; export default configureStore( reducer:  users: usersReducer, tasks: tasksReducer, >, >); 

      В примере выше мы видим два редьюсера, которые передаются под разными ключами — users и tasks . Мы можем придумывать любые имена ключей, но будет понятнее, если имена будут соответствовать содержимому. Например, редьюсер для списка пользователей лучше назвать users , а для списка задач — tasks .

      Теперь наш стор готов к использованию, и мы можем подключить его в приложение. Создавать приложение начнем с верхнего уровня. Здесь понадобится компонент , который содержит хранилище и прокидывает его вглубь дерева компонентов через контекст:

      // file: index.jsx import React from 'react'; import ReactDOM from 'react-dom/client'; import  Provider > from 'react-redux'; import App from './components/App.jsx'; import store from './slices/index.js'; const mountNode = document.getElementById('container'); const root = ReactDOM.createRoot(mountNode); // Оборачиваем приложение в Provider // И передаем в него хранилище root.render( Provider store=store>> App /> /Provider>, ); 

      Теперь самое главное — Toolkit в действии. Здесь мы опираемся на работу хуков. Здесь все работает по-прежнему:

      • Чтобы изменить состояние в хранилище, нужно передать экшн в функцию dispatch()
      • Чтобы получить объект dispatch в компоненте, нужно использовать функцию useDispatch()
      • Чтобы извлечь данные из стора, нужно использовать хук useSelector() . Он принимает функцию, в которую через параметр передается все состояние. Возвращаемое значение из этой функции станет результатом выполнения useSelector()

      Посмотрим, как это работает:

      // file: components/App.jsx import React from 'react'; // Хуки находятся в react-redux import  useSelector, useDispatch > from 'react-redux'; // Импортируем нужные действия import  decrement, increment, incrementByAmount > from '../slices/counterSlice.js'; export default () =>  // Вытаскиваем данные из хранилища. state — все состояние const count = useSelector((state) => state.counter.value); // Возвращает метод store.dispatch() текущего хранилища const dispatch = useDispatch(); return ( div> div> button aria-label="Increment value" onClick=() => dispatch(increment())> > Прибавить button> span>count>span> button aria-label="Decrement value" onClick=() => dispatch(decrement())> > Отнять button> br /> button onClick=() => dispatch(incrementByAmount(42))>>Прибавить 42button> div> div> ); >; 

      В компоненте может быть несколько вызовов useSelector , причем каждый вызов создаст подписку на изменение состояния. Срабатывание нескольких подписок одновременно приведет только к одной перерисовке компонента.

      Обратите внимание, что функция переданная в useSelector принимает все состояние целиком. Если у нас несколько редьюсеров и слайсов, состояние содержит все состояния этих слайсов.

      Состояние хранится в объекте, где каждый ключ — это то, что мы указали в reducer при создании стора. В нашем случае, это свойство counter :

      export default configureStore( reducer:  // Свойство `counter` будет внутри объекта общего состояния `state.counter` counter: counterReducer, >, >); 

      Открыть доступ

      Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

      • 130 курсов, 2000+ часов теории
      • 1000 практических заданий в браузере
      • 360 000 студентов

      Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *