Redux 和 Context API 與 React Native App:簡(jiǎn)介、用例、實(shí)施和比較

言鼎科技 2023-07-01 454

如果您有 Javascript 背景,那么您可能熟悉術(shù)語(yǔ)Redux 和 Context API。并且可能,您可能遇到過(guò)很多關(guān)于哪個(gè)更好的博客——Redux 與 Context API。我假設(shè)相同,除非我意識(shí)到它不是!

在閱讀了一堆博客之后,我總結(jié)了這兩種工具的用途以及它們之間的區(qū)別。如果您還不知道,請(qǐng)不要擔(dān)心,本教程將通過(guò)一個(gè)基本的演示示例幫助您了解這兩種工具的用例。在這里,我們將使用這兩種方法構(gòu)建一個(gè)應(yīng)用程序并討論它們。

那我們開始吧!

教程目標(biāo)

  • 了解 Redux 和上下文 API

  • 比較 Redux 和 Context API 的工作

  • 探索 Redux 和 Context API 的目的和用例

  • 使用 Redux 和 Context API 方法的演示應(yīng)用程序

Redux:簡(jiǎn)介和構(gòu)建塊

根據(jù)文件-

Redux 是一種模式和庫(kù),用于使用稱為“動(dòng)作”的事件來(lái)管理和更新應(yīng)用程序狀態(tài)。它作為需要在整個(gè)應(yīng)用程序中使用的狀態(tài)的集中存儲(chǔ),其規(guī)則確保狀態(tài)只能以可預(yù)測(cè)的方式更新。

文檔中明確提到 redux 是為了“管理狀態(tài)”,理解狀態(tài)是如何更新的。

Redux 的用例

  • 如文檔中所述,redux 的主要目標(biāo)是管理和跟蹤狀態(tài)。

  • 將狀態(tài)管理邏輯與用戶界面層分開

  • 更快的邏輯調(diào)試

Redux 主要用于集中管理 React 應(yīng)用程序的狀態(tài),可以在應(yīng)用程序的任何位置訪問(wèn)狀態(tài)。從技術(shù)上講,Redux 的概念是基于 Flux 架構(gòu)的,這個(gè)概念并不局限于 React 應(yīng)用程序;也有不同技術(shù)的實(shí)現(xiàn)(例如 Angular 的 NgRx)。但是 Redux 特別是用 React 實(shí)現(xiàn)的。

你可能喜歡閱讀:

如何在 React Native 應(yīng)用程序中使用 Redux 和 React Hooks

需要的包裹

  • redux :用于createStore()、combineReducer()等函數(shù)。

  • react-redux :用于connect()等功能。

Redux 的構(gòu)建塊

它主要由四個(gè)構(gòu)建塊組成:

1. Reducer:這些是將狀態(tài)和動(dòng)作作為參數(shù)傳入的函數(shù)。它在返回更改值的開關(guān)案例中包含“action.type” 。它可選擇接受有效負(fù)載(通常在稱為reducers.js 的單獨(dú)文件中創(chuàng)建)

2. Store:Store是所有數(shù)據(jù)的集合。您可以將其傳遞給提供商。

3. Provider:接受 store 作為參數(shù)的 React 組件(通常在index.js中創(chuàng)建)

4. 動(dòng)作:向調(diào)度器提供/返回動(dòng)作類型和有效負(fù)載的函數(shù),調(diào)度器將進(jìn)一步調(diào)用相應(yīng)的 reducer(通常在稱為actions.js的單獨(dú)文件中創(chuàng)建)


上下文 API:簡(jiǎn)介和構(gòu)建塊

React 文檔將 context API 解釋為 -
Context 提供了一種通過(guò)組件樹傳遞數(shù)據(jù)的方法,而無(wú)需在每個(gè)級(jí)別手動(dòng)傳遞 props。

在典型的 React 應(yīng)用程序中,數(shù)據(jù)通過(guò) props 自上而下(父到子)傳遞,但對(duì)于應(yīng)用程序中許多組件所需的某些類型的 props(例如語(yǔ)言環(huán)境首選項(xiàng)、UI 主題),這種使用可能很麻煩。Context 提供了一種在組件之間共享這些值的方法,而無(wú)需顯式地通過(guò)樹的每個(gè)級(jí)別傳遞 prop。

如果您可以觀察“傳遞”“共享”值的文檔狀態(tài)上下文,而沒(méi)有提及“管理狀態(tài)”

上下文 API 的用例

使用上下文 API 的主要目的是避免“prop drilling”——在每個(gè)級(jí)別傳遞 prop。它更像是用于將值從一端傳遞到另一端的管道。

上下文 API 提供了通過(guò)組件樹傳遞數(shù)據(jù)的最簡(jiǎn)單方法,這樣您就不必在每個(gè)級(jí)別手動(dòng)傳遞道具。例如,假設(shè)我們有一個(gè)由 A、B、C 和 D 組件組成的組件樹?,F(xiàn)在你需要將 props 從 A 傳遞到 D,而不是傳遞它 A > B > C > D,即傳遞給每個(gè)組件,在上下文的幫助下你可以直接傳遞到 A > D。

現(xiàn)在,許多博客都提到 Context API 是 Redux 的最佳替代品,因?yàn)樗莾?nèi)置的,您不必為此安裝依賴項(xiàng)。這是真的嗎——Context API 可以取代 Redux 嗎?我們將在下一節(jié)中對(duì)此進(jìn)行討論。請(qǐng)繼續(xù)關(guān)注探索!

上下文 API 的構(gòu)建塊

我們可以將上下文 API 分為三個(gè)塊:
1. 上下文:使用將默認(rèn)值作為第一個(gè)參數(shù)的createContext()函數(shù)。在這里傳遞 Javascript 對(duì)象是可選的。您可以在您的應(yīng)用程序中實(shí)現(xiàn)多個(gè)上下文。

2.Provider:Provider創(chuàng)建context后,提供訪問(wèn)context的能力。它提供函數(shù)和數(shù)據(jù)以將值進(jìn)一步傳遞給組件。

3. Consumer:Consumer 允許訪問(wèn) Provider 包裝的子組件的值。它有兩種類型——

  • Context.Consumer: Context.Consumer可用于功能組件和基于類的組件。但是,通過(guò)這種方法,上下文只能在渲染方法中訪問(wèn)。

  • 靜態(tài)上下文類型: 靜態(tài)上下文類型只能用于基于類的組件。

Redux 和上下文 API 示例

  • 下面的示例基于計(jì)數(shù)器。初始值為 0,它有兩個(gè)按鈕來(lái)遞增和遞減該值。

  • 在主父計(jì)數(shù)器組件內(nèi),將有三個(gè)子組件-

? 一個(gè)用于更改計(jì)數(shù)器值
? 每個(gè)按鈕兩個(gè)。

Context 和 Redux 方法的初始設(shè)置是相同的。

您是否正在為在 Context 和 Redux 方法之間做出選擇并在您的應(yīng)用程序中實(shí)施它而苦惱?與最好的React Native App Development Company
取得聯(lián)系,他們擁有具有此類專業(yè)知識(shí)的開發(fā)人員,可以輕松無(wú)痛地實(shí)施!

創(chuàng)建 React Native 應(yīng)用程序

最初,使用以下命令創(chuàng)建一個(gè) React Native 應(yīng)用程序


反應(yīng)本機(jī)初始化 CounterDemo

Redux 方法:如何在 React Native App 中實(shí)現(xiàn) Redux?

安裝 Redux 所需的依賴項(xiàng)


npm 安裝 redux --savenpm 安裝 react-redux --save

Redux 商店設(shè)置

我們將在App.js文件中創(chuàng)建我們的商店。

// 應(yīng)用程序.js


import React, { Component } from 'react';從'react-redux'導(dǎo)入{Provider};從'redux'導(dǎo)入{createStore};從 './reducers/index.js' 導(dǎo)入 totalReducers;從'./components/counters'導(dǎo)入計(jì)數(shù)器;
const store = createStore(totalReducers);
導(dǎo)出默認(rèn)類 App extends Component{
 使成為(){
   返回(
     
   );
 }}
  • 這里我們導(dǎo)入總減速器從減速器文件夾。

  • 創(chuàng)建商店()函數(shù)接受一個(gè)參數(shù)作為總減速器對(duì)象并生成商店。

  • Provider 組件確保商店在整個(gè)應(yīng)用程序中可用。

減速器設(shè)置

減速器返回應(yīng)用程序所需的數(shù)據(jù)。在此演示中,reducer 將返回更新后的計(jì)數(shù)器值。這是reducers 文件夾中的counterReducer.js文件。

// 減速器/counterReducer.js


讓計(jì)數(shù)= 0;
導(dǎo)出默認(rèn)值(狀態(tài)=計(jì)數(shù),動(dòng)作)=> {
   開關(guān)(動(dòng)作類型){
       案例“增量”:
           計(jì)數(shù)++
           休息;
       案例“減量”:
           數(shù)數(shù)  -
           休息;
       默認(rèn):
           數(shù)數(shù);
   }
   返回計(jì)數(shù);  }

解釋

  • 上面定義的 reducer 將始終返回計(jì)數(shù)值。

  • 增量和減量是將更新值的操作類型,如上所示。

  • 我們將在 reducers 文件夾內(nèi)的 index.js 文件中組合所有的 reducer。

// reducers/index.js


從'redux'導(dǎo)入{combineReducers};從 './counterReducer' 導(dǎo)入 counterReducer;
const totalReducers= combineReducers({
 計(jì)數(shù):counterReducer,});
導(dǎo)出默認(rèn)的 totalReducers;

解釋

  • 在這里,我們將把所有的 reducer 組合起來(lái)作為Redux 庫(kù)的combineReducers()函數(shù)的參數(shù)。

動(dòng)作設(shè)置

創(chuàng)建兩個(gè)動(dòng)作:增量和減量

// 動(dòng)作/index.js


導(dǎo)出函數(shù)增量(){
   返回{
     類型:“增量”
   };
 }
導(dǎo)出函數(shù)遞減(){
 返回{
   類型:“遞減”
 };}

界面組件

我們將只創(chuàng)建一個(gè)稱為計(jì)數(shù)器組件的組件。為了使用 reducer 和 action,我們必須實(shí)現(xiàn)這些功能:

  • mapStateToProps() – 它只是接受你的 reducer 數(shù)據(jù),并將其轉(zhuǎn)換成一個(gè)簡(jiǎn)單可用的 prop。在this.props.data的幫助下,我們將在組件中使用數(shù)據(jù)作為道具。


函數(shù) mapStateToProps(狀態(tài)){
   返回{
     計(jì)數(shù):state.count
   };}

注意:請(qǐng)記住我們是如何在 combineReducers 函數(shù)中為 reducer 分配名稱的,因?yàn)槲覀儽仨毷褂孟嗤拿Q來(lái)調(diào)用各個(gè) reducer。

  • mapDispatchToProps() – 它接受你的動(dòng)作,并將它們轉(zhuǎn)換成一個(gè)簡(jiǎn)單的可用道具。


函數(shù) mapDispatchToProps(調(diào)度){
       返回 bindActionCreators({增量,減量},分派)}

注意:bindActionCreators函數(shù)只是將我們的動(dòng)作組合到一個(gè)對(duì)象中。

轉(zhuǎn)向管理用戶界面的組件。

// 組件/counter.js


類計(jì)數(shù)器擴(kuò)展組件{
 構(gòu)造函數(shù)(道具){
   超級(jí)(道具);
 }

 使成為() {
   返回 (
     
         {'Redux 方法'}
       {this.props.count}this.props.increment()}>            增量+this.props.decrement()}>            遞減 -
   );
 }}
函數(shù) mapStateToProps(狀態(tài)){
 返回 {
   計(jì)數(shù):state.count,
 };}
函數(shù) mapDispatchToProps(調(diào)度){
 返回 bindActionCreators({increment, decrement}, dispatch);}
導(dǎo)出默認(rèn)連接(mapStateToProps,mapDispatchToProps)(計(jì)數(shù)器);

要設(shè)置組件樣式,您可以使用以下代碼


const styles = StyleSheet.create({
 主容器:{
   彈性:1,
   justifyContent: '中心',
   alignItems: '中心',
 },
 柜臺(tái)號(hào)碼:{
   字體大?。?5,
   fontWeight: '粗體',
 },
 按鈕容器:{
   flexDirection: '行',
 },
 按鈕樣式:{
   背景顏色:'綠色',
   邊框?qū)挾龋?,
   身高:30,
   寬度:'25%',
   邊界半徑:5,
   justifyContent: '中心',
   alignItems: '中心',
 },});

整理起來(lái)

到目前為止,我們已經(jīng)完成了計(jì)數(shù)器演示的 redux 設(shè)置、邏輯和用戶界面?,F(xiàn)在,只剩下一個(gè)簡(jiǎn)單的步驟——將我們的 App 文件導(dǎo)入到我們的 index.js 文件中。

// 索引.js


從 'react-native' 導(dǎo)入 {AppRegistry};從'./src/App.js'導(dǎo)入應(yīng)用程序;從 './app.json' 導(dǎo)入 {name as appName};
AppRegistry.registerComponent(appName, () => App);

Git 回購(gòu)鏈接:https://github.com/sunil-bacancy/CounterDemo

Context API 方法:如何在 React Native App 中實(shí)現(xiàn) Context API?

由于上下文 API 是內(nèi)置功能,我們不需要安裝第三方依賴項(xiàng)。


文件夾結(jié)構(gòu)

在您的應(yīng)用程序的根目錄下創(chuàng)建一個(gè)文件夾src 。src文件夾中,我們必須創(chuàng)建 3 個(gè)文件夾,分別是reducers、components、state和一個(gè)文件App.js。

減速器設(shè)置

就像 Redux 一樣,使用 Context API 聲明 reducer。

// 減速器/globalReducer.js


export default countReducer = (state, action) => {
   開關(guān)(動(dòng)作類型){
       案例“增量”:
           返回{
               ...狀態(tài),
               計(jì)數(shù)器:state.counter + 1,
           }
       案例“減量”:
           返回{
               ...狀態(tài),
               計(jì)數(shù)器:state.counter - 1,
           }
       默認(rèn):
           返回{
               狀態(tài)
           }
   }  }

創(chuàng)建上下文

  • 使用createContext()創(chuàng)建上下文并將初始狀態(tài)作為參數(shù)傳遞。您也可以在不傳遞參數(shù)的情況下進(jìn)行定義。

  • 定義一個(gè)將通過(guò) Provider 傳遞數(shù)據(jù)的函數(shù)。

  • useReducer()將采用具有默認(rèn)狀態(tài)的 reducer,然后返回更新后的值并分派該函數(shù)。

  • 在 Provider 函數(shù)中,使用帶參數(shù)的useReducer() - reducer 和初始狀態(tài)。返回和調(diào)度狀態(tài)稍后作為值傳遞給提供者。

// 狀態(tài)/globalState.js


從“反應(yīng)”中導(dǎo)入反應(yīng),{createContext,useReducer};從 '../reducers/globalReducer' 導(dǎo)入 countReducer;
const 初始狀態(tài) = {
   計(jì)數(shù)器:0}
export const GlobalContext = createContext(initialState);
導(dǎo)出默認(rèn) GlobalProvider = ({children}) => {
   const [state, dispatch] = useReducer(countReducer, initialState);

   返回(
       
           {孩子們}
       
   )}

提供上下文

創(chuàng)建上下文后,我們需要提供上下文,以便在子組件中可以訪問(wèn)它。為此,您需要將其包裝在 Provider 中。

// 源代碼/App.js


import React, { Component } from 'react';從“./state/globalState”導(dǎo)入 GlobalProvider;從'./components/counter'導(dǎo)入計(jì)數(shù)器;
導(dǎo)出默認(rèn)類 App 擴(kuò)展組件 {
   使成為(){
       返回 (
           
       )
   }}

消費(fèi)語(yǔ)境

使用 useContext() 在各個(gè)子組件中使用上下文。

// 組件/counter.js


從'react'導(dǎo)入React,{Component,useContext};import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';從 '../state/globalState' 導(dǎo)入 {GlobalContext};
常量計(jì)數(shù)器 = () => {

  const {state} = useContext(GlobalContext);
  const {dispatch} = useContext(GlobalContext);

  返回(
     
           {'上下文 API 方法'}
                { 狀態(tài). 計(jì)數(shù)器 }
             調(diào)度({類型:“增量”})}
                  >
                   
                      增量+
                    調(diào)度({類型:“遞減”})}
                  >
                   
                      遞減 -
                   
   )}
導(dǎo)出默認(rèn)計(jì)數(shù)器;

要為您的組件設(shè)置樣式,您可以使用以下代碼。


const styles = StyleSheet.create({
   主容器:{
       彈性:1,
       justifyContent: '中心',
       alignItems: '中心'
   },
   柜臺(tái)號(hào)碼:{
       字體大?。?5,
       fontWeight: '粗體'
   },
   按鈕容器:{
       flexDirection: '行'
   },
   按鈕樣式:{
       背景顏色:'綠色',
       邊框?qū)挾龋?,
       身高:30,
       寬度:'25%',
       邊界半徑:5,
       justifyContent: '中心',
       alignItems: '中心',
   },})

Git 回購(gòu)鏈接:https://github.com/sunil-bacancy/CounterContextDemo

Redux 和 Context API:比較

終極版

  • 存儲(chǔ)和管理值

  • 在 React 組件之外工作

  • 避免螺旋鉆

  • 通過(guò)調(diào)度一個(gè)動(dòng)作,可以更新值

  • 提供 DevTools 以顯示操作和狀態(tài)值的歷史記錄

  • 允許應(yīng)用程序代碼通過(guò)中間件觸發(fā)副作用

上下文API

  • 不用于存儲(chǔ)或管理值

  • 僅適用于 React 組件

  • 傳遞單個(gè)值,可以是對(duì)象、基元、類等。

  • 避免螺旋鉆

  • 為提供者和消費(fèi)者提供當(dāng)前上下文值,但不顯示值更改方式的任何歷史記錄。

  • 排除副作用機(jī)制——專用于組件渲染

結(jié)論

我希望本教程能幫助您了解 Context 和 Redux 的不同之處。此外,嘗試實(shí)現(xiàn)這兩種方法并使用代碼進(jìn)行更深入的挖掘。對(duì)于更多此類 React Native 教程,我們有一個(gè)React Native 教程頁(yè)面,其中包含帶有 github 源的分步指南。

我可以理解為一個(gè)復(fù)雜的應(yīng)用程序組織和管理全局存儲(chǔ)有多么困難,以及在您的應(yīng)用程序中實(shí)現(xiàn) Context API 需要多么精確。如果您有一個(gè)龐大而復(fù)雜的項(xiàng)目并且想要實(shí)施 Redux 或 Context API,請(qǐng)隨時(shí)聯(lián)系我們并聘請(qǐng)React Native 開發(fā)人員。

言鼎科技

The End