Redux 和 Context API 與 React Native App:簡(jiǎn)介、用例、實(shí)施和比較
如果您有 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)的。
需要的包裹
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ā)人員。