В чем отличие Context от Redux?
С релизом нового Context API (начиная с React 16.3) среди разработчиков не утихают споры, что лучше использовать для управления состоянием React-приложений, библиотеку Redux или же Context
Попробуем разобраться, чем отличаются эти инструменты и уместно ли их противопоставлять.
Что же такое React Context?
Прежде всего стоит посмотреть, на определение, предоставленное официальной документацией React: "Контекст позволяет передавать данные через дерево компонентов без необходимости передавать пропсы на промежуточных уровнях."
Из определения следует, что Context предназначен для организации доступа к каким-либо данным из разных частей приложения без необходимости явно прокидывать пропсы по дереву компонентов, но нигде не идёт речи об управлении состоянием. Т.е. Context в своем базовом виде не является инструментом для управления состоянием.
Фактически в приложениях, использующих Context для управлением состоянием, управление осуществляется в родительском компоненте с помощью хуков useState/useReducer. Компонент рендерит <MyContext.Provider> и предоставляется состояние через value.
При этом при изменении какой-то части value будут обновляться все компоненты подписанные на Context, даже если в value обновилось поле, которое компонент не использует. Следует это учитывать при попытке использовать Context и useReducer для управления глобальным состоянием. В этом случае потребуется реализовывать дополнительную логику для избежания ненужных обновлений компонентов.
Что такое Redux?
Здесь также уместно будет обратиться к официальной документации: "Redux это паттерн и библиотека для управления и обновления состояния приложения с помощью событий, называемых “экшены” (Actions). Redux создает централизованное хранилище состояния, которое может быть использовано во всём приложении и будет обновляться только предсказуемым образом." Здесь явно указано, что Redux разработан именно для управления состоянием.
Redux предоставляет отдельное расширение для браузера - Redux Devtools, которое позволяет отслеживать историю экшенов и видеть все изменения состояния в процессе использования состояния. Также в Redux возможно подключение мидлваров - это специальные функции или целые библиотеки, позволяющие управлять сайд-эффектами и реализовывать различные дополнительные возможности.
Сам по себе Redux не привязан к React и может использоваться с любой реализацией UI или вообще работать без какого-либо UI. Но исторически сложилось, что по большей части Redux используется именно в React-приложениях. Это реализуется посредством библиотеки React-Redux, которая связывает хранилище Redux с приложением.
Внутри React-Redux также использует контекст для предоставления приложению доступа к состояния, но в данном случае передается не значение состояния (фактические данные), а инстанс стора (store) - объекта, который содержит методы для получения и изменения состояния. Далее компоненты получают доступ к состоянию с через хук useSelector или HOC (higher order component) connect. Компонент будет обновляться только при обновлении тех значений полей состояния, на который он подписан.
Когда использовать Context, когда Redux?
Context следует использовать, если требуется предоставить компонентам какие-либо данные и избежать их прокидывания по всему дереву через пропсы.
Что касается управления состоянием, то также для относительно простых приложений можно использовать управление состоянием с помощью useState/useReducer и предоставлять это состояние приложению через Context.
Redux подойдет для более сложных проектов, где требуется:
- реализация различных сайд-эффектов при обновлении состояния;
- явное отделение бизнес-логики от UI;
- отслеживание и логгирование всех обновлений состояния.