摘要:歸約器函數(shù)負(fù)責(zé)返回應(yīng)用當(dāng)前全局狀態(tài)的表示形式。當(dāng)我們在存儲上發(fā)送操作時(shí)將使用應(yīng)用的當(dāng)前狀態(tài)和導(dǎo)致狀態(tài)更新的操作來調(diào)用此歸約器函數(shù)?;氐轿覀兊臍w約器我們可以檢查的動作類型并采取適當(dāng)?shù)牟襟E創(chuàng)建下一個(gè)狀態(tài)。我們將處理動作創(chuàng)造者中歸約器的副作用。
本文轉(zhuǎn)載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3811
原文:https://www.fullstackreact.com/30-days-of-react/day-19/
隨著我們了解了flux和Redux的知識,讓我們將Redux整合到我們的應(yīng)用中,并通過連接的應(yīng)用。
昨天, 我們討論了流量模式的原因, 它是什么, 我們有不同的選擇, 以及介紹了Redux。
今天, 我們將回到代碼和添加Redux在我們的應(yīng)用?,F(xiàn)在我們正在用它構(gòu)建的應(yīng)用是簡單的, 這只會顯示我們最后一次獲取當(dāng)前時(shí)間的頁面。為了簡單起見, 我們不會調(diào)用遠(yuǎn)程服務(wù)器, 只需使用 JavaScript 的Date 對象。
第一件事, 我們使用redux將不得不安裝redux庫。我們可以使用npm 包管理器來安裝redux。在我們以前構(gòu)建的應(yīng)用的根目錄中, 讓我們運(yùn)行npm install 命令來安裝redux:
npm install --save redux
想使用redux, 我們還需要安裝另一個(gè)包, react-redux , 幫助我們把react 和 redux綁在一起。
npm install --save react-redux配置和設(shè)置
接下來的工作, 我們需要做的是在我們的應(yīng)用內(nèi)建立redux。我們需要執(zhí)行以下操作才能設(shè)置它:
定義歸約
創(chuàng)建Store
創(chuàng)建動作創(chuàng)造者
將Store與我們的React意見聯(lián)系起來
得益
Precursor先驅(qū)第5步?jīng)]有promises, 但它會更好, 嗯?
我們少量地討論術(shù)語,(讓我們的手指移動是更重要的)。我們將只是稍微調(diào)整我們的應(yīng)用(煩人, 我知道, 但這是最后一次), 所以我們?yōu)榱颂峁?shù)據(jù)通過我們的應(yīng)用可以創(chuàng)建一個(gè)包裝組件。
完成后, 我們的應(yīng)用樹將具有以下形狀:
[Root] -> [App] -> [Router/Routes] -> [Component]
廢話少說, 讓我們將我們的 src/App.js 移動到src/containers目錄中, 我們需要同時(shí)更新來自我們的導(dǎo)入的一些路徑。我們將使用幾天前討論的React路由材料。
我們將在
import React from "react"; import { BrowserRouter as Router, Route, Switch } from "react-router-dom" // We"ll load our views from the `src/views` // directory import Home from "./views/Home/Home"; import About from "./views/About/About"; const App = props => { return () } export default App;
此外, 我們將需要?jiǎng)?chuàng)建一個(gè)新的容器, 我們將調(diào)用Root , 這將包裝我們的整個(gè)
`touch src/containers/Root.js`
目前, 我們將在這里使用一個(gè)占位符組件, 但我們將在討論存儲時(shí)替換此內(nèi)容?,F(xiàn)在, 讓我們導(dǎo)出 _一些東西_:
import React from "react"; import App from "./App"; const Root = (props) => { return (); } export default Root;
最后, 讓我們更新的路由, 我們渲染我們的應(yīng)用在src/index.js文件使用我們的新的Root 容器, 而不是它以前使用的App 。
import React from "react"; import ReactDOM from "react-dom"; import Root from "./containers/Root"; import "./index.css"; ReactDOM.render(添加Redux, document.getElementById("root") );
現(xiàn)在有了一個(gè)堅(jiān)實(shí)的應(yīng)用結(jié)構(gòu)就位, 我們可以開始添加Redux。我們將采取的步驟以配合一些我們將建立的大多數(shù)應(yīng)用的Redux結(jié)構(gòu)通常都是相同的。我們需要:
寫一個(gè)根歸約器
寫 actionCreators
配置存儲、rootReducer和應(yīng)用
將視圖連接到 actionCreators
我們故意保持這個(gè)高層次的介紹短一些, 所以堅(jiān)持一下, 這一切都將在短期內(nèi)變得更有意義。
讓我們設(shè)置允許我們添加Redux的結(jié)構(gòu)。我們將在src/redux 目錄中完成幾乎所有的工作。讓我們創(chuàng)建該目錄。
mkdir -p src/redux touch src/redux/configureStore.js touch src/redux/reducers.js
首先我們先創(chuàng)建歸約器。雖然它聽起來很復(fù)雜, 但是歸約器實(shí)際上是相當(dāng)直接的, 有一定的經(jīng)驗(yàn)。歸約器僅是 字面 函數(shù)。它的唯一責(zé)任是返回一個(gè) next 狀態(tài)的表示。
在Redux模式, 不像flux, 我們只在 整個(gè) 應(yīng)用處理 一個(gè) 全局存儲的。這使得事情變得更容易處理, 因?yàn)橛幸粋€(gè)地方的數(shù)據(jù), 我們的應(yīng)用生活。
root 歸約器函數(shù)負(fù)責(zé)返回應(yīng)用當(dāng)前全局狀態(tài)的表示形式。當(dāng)我們在存儲上發(fā)送操作時(shí), 將使用應(yīng)用的當(dāng)前狀態(tài)和導(dǎo)致狀態(tài)更新的操作來調(diào)用此歸約器函數(shù)。
讓我們在一個(gè)文件中建立我們的根歸約器在src/redux/reducers.js.。
// Initial (starting) state const initialState = { currentTime: new Date().toString() } // Our root reducer starts with the initial state // and must return a representation of the next state const rootReducer = (state = initialState, action) => { return state; } export default rootReducer
I在函數(shù)中, 我們將第一個(gè)參數(shù)定義為初始狀態(tài) (第一次運(yùn)行時(shí), 不帶參數(shù)調(diào)用rootReducer , 因此它總是在第一次運(yùn)行時(shí)返回 initialState )。
這就是現(xiàn)在的 rootReducer。就像現(xiàn)在這樣, state的價(jià)值總是和 initialState 一樣。在我們的例子中, 這意味著我們的數(shù)據(jù)樹有一個(gè)單一的currentTime鍵。
什么是動作?這里的第二個(gè)參數(shù)是從存儲區(qū)發(fā)送的操作。我們很快就會回來。現(xiàn)在,讓我們來看看動作。
最起碼, 一個(gè)動作 必須 包括一個(gè)type 鍵。type 鍵可以是我們想要的任何值, 但它必須存在。例如, 在我們的應(yīng)用中, 我們將偶爾發(fā)送一項(xiàng)操作, 我們想告訴存儲獲取 最新 當(dāng)前時(shí)間。我們可以將此操作稱為FETCH_NEW_TIME 的字符串值。
我們可能從我們的存儲發(fā)送的處理此更新的操作如下:
{ type: "FETCH_NEW_TIME" }
正如我們將通過鍵入這個(gè)字符串很多, 我們希望避免可能的拼寫錯(cuò)誤的地方, 它是常見的創(chuàng)建一個(gè)types.js 文件, 將操作類型導(dǎo)出為常量。讓我們遵循這個(gè)約定, 創(chuàng)建一個(gè)src/redux/types.js 文件:
`export const FETCH_NEW_TIME = "FETCH_NEW_TIME";`
我們將從types.js 文件中引用它, 而不是使用"FETCH_NEW_TIME" 的硬編碼字符串調(diào)用該操作:
import * as types from "./types"; { type: types.FETCH_NEW_TIME, }
當(dāng)我們想發(fā)送數(shù)據(jù)與我們的動作, 我們可以添加任何鍵, 我們想我們的動作。我們通常會看到這個(gè)所謂的payload 有效載荷, 但它可以被稱為任何東西。這是一個(gè)公約, 調(diào)用附加信息的payload。
我們的FETCH_NEW_TIME 動作將發(fā)送一個(gè)有效載荷與新的當(dāng)前時(shí)間。因?yàn)槲覀兿氚l(fā)送一個(gè) 序列化 值與我們的動作, 我們將發(fā)送新的當(dāng)前時(shí)間的字符串值。
{ type: types.FETCH_NEW_TIME, payload: new Date().toString() // Any serializable value }
回到我們的歸約器, 我們可以檢查的動作類型, 并采取適當(dāng)?shù)牟襟E, 創(chuàng)建下一個(gè)狀態(tài)。在我們的情況下, 我們只儲存payload。如果操作的type 是FETCH_NEW_TIME, 我們將返回新的 currentTime (從我們的操作有效負(fù)載) 和其他狀態(tài) (使用 ES6 擴(kuò)展語法):
export const rootReducer = (state = initialState, action) => { switch(action.type) { case types.FETCH_NEW_TIME: return { ...state, currentTime: action.payload} default: return state; } }
請記住, 歸約 必須 返回一個(gè)狀態(tài), 所以在默認(rèn)情況下, _最起碼_確保返回當(dāng)前狀態(tài)。
保持輕型化由于歸約器的功能每次調(diào)度一個(gè)動作, 我們要確保這些功能是盡可能簡單和快速。我們不希望他們造成任何副作用或有太多的延遲。
我們將處理動作創(chuàng)造者中歸約器的副作用。
在我們看動作創(chuàng)造者 (以及為什么我們稱他們?yōu)閯幼鲃?chuàng)造者) 之前, 讓我們把我們的存儲與我們的應(yīng)用掛鉤。
我們將使用 react-redux 包將我們的視圖連接到我們的redux存儲。讓我們確保使用npm安裝此包:
npm install --save react-redux將存儲與視圖掛鉤
react-redux 包輸出一個(gè)名為 Provider 的組件。Provider 組件使存儲可以使用我們的應(yīng)用中的所有容器組件, 而無需我們每次都需要手動傳遞它。
Provider 組件期望一個(gè)store 的屬性, 它期望是一個(gè)有效的redux存儲, 所以我們的應(yīng)用沒有錯(cuò)誤運(yùn)行之前,我們需要完成一個(gè)configureStore 功能,?,F(xiàn)在, 讓我們在應(yīng)用中連接Provider 組件。我們將通過更新我們以前創(chuàng)建的包裝Root 組件來使用Provider 組件來完成此項(xiàng)。
import { Provider } from "react-redux"; // ... const Root = (props) => { // ... return (); }
請注意, 我們正在將store 值發(fā)送到Provider 組件, 但我們還沒有創(chuàng)建該存儲?,F(xiàn)在我們來解決這個(gè)問題。
配置存儲為了創(chuàng)建一個(gè)存儲, 我們將使用新的src/redux/configureStore.js 來導(dǎo)出將負(fù)責(zé)創(chuàng)建存儲的函數(shù)。
我們?nèi)绾蝿?chuàng)建一個(gè)存儲?
redux包輸出一個(gè)叫做 createStore 的函數(shù), 它將為我們創(chuàng)建實(shí)際的存儲區(qū), 因此, 讓我們打開 src/redux/configureStore.js 文件并導(dǎo)出一個(gè)稱為configureStore()的函數(shù) (我們將很快定義), 并導(dǎo)入createStore` 幫助器:
import {createStore} from "redux"; // ... export const configureStore = () => { // ... } // ... export default configureStore;
實(shí)際上我們在我們的存儲還沒有返回任何東西, 所以讓我們實(shí)際創(chuàng)建的redux 存儲使用 createStore 的功能, 我們從redux導(dǎo)入:
import {createStore} from "redux"; export const configureStore = () => { const store = createStore(); return store; } export default configureStore;
如果我們在瀏覽器中加載我們的頁面, 我們將看到我們有一個(gè)巨大的錯(cuò)誤: 沒有頁面得到渲染。
redux給我們的錯(cuò)誤告訴我們, 我們存儲里沒有歸約器。如果沒有歸約器, 它將不知道如何處理動作或如何創(chuàng)建狀態(tài)等。為了越過這個(gè)錯(cuò)誤, 我們需要參考我們創(chuàng)建的 rootReducer。
createStore 函數(shù)要求我們將 rootReducer 作為第一個(gè)參數(shù)來傳遞。它還希望將初始狀態(tài)作為第二個(gè)參數(shù)傳遞。我們將從我們創(chuàng)建的reducers.js 文件中導(dǎo)入這兩個(gè)值。
import { rootReducer, initialState } from "./reducers" // ... export const configureStore = () => { const store = createStore( rootReducer, // root reducer initialState, // our initialState ); return store; }
現(xiàn)在, 讓我們通過調(diào)用 configureStore() 函數(shù)創(chuàng)建store 的實(shí)例來更新我們的Root.js 文件。
const Root = (props) => { const store = configureStore(); return (連接視圖 (續(xù))); }
我們的應(yīng)用中的一切都設(shè)置為使用redux, 而無需 太 多開銷。redux 提供的一個(gè)更方便的方法是使用react-redux包導(dǎo)出的connect() 函數(shù), 將狀態(tài)樹的片斷 綁定 到不同的組件。
connect() 函數(shù)返回一個(gè)函數(shù), 它期望第一參數(shù)是一個(gè)組件。這通常叫做高階組件。
connect() 函數(shù)要求我們在函數(shù)中至少傳遞一個(gè)參數(shù) (但通常我們會傳遞兩個(gè))。它所期望的第一個(gè)參數(shù)是一個(gè)函數(shù), 它將被稱為state 并期望一個(gè)返回的對象將數(shù)據(jù)連接到視圖。讓我們看看我們是否能在代碼中揭開這種行為的神秘面紗。
我們將這個(gè)函數(shù)稱為mapStateToProps 函數(shù)。因?yàn)樗呢?zé)任是將狀態(tài)映射到與組件的原始props合并的對象。
讓我們在src/views/Home.js 中創(chuàng)建 home 視圖, 并使用此connect() 函數(shù)來綁定currentTime 在我們的狀態(tài)樹中的值。
import { connect } from "react-redux"; // ... const mapStateToProps = state => { return { currentTime: state.currentTime } } export default connect( mapStateToProps )(Home);
此connect() 函數(shù) 自動 將函數(shù)的第一個(gè)參數(shù)中的任何鍵傳遞為Home 組件的props 。
在我們的演示案例中, Home 組件中的currentTime屬性將映射到currentTime中的狀態(tài)樹鍵。讓我們更新 Home 組件, 以顯示currentTime中的值:
const Home = (props) => { return (); }Welcome home!
Current time: {props.currentTime}
雖然這個(gè)演示不是很有趣, 它表明我們有我們的Redux 應(yīng)用建立了我們的 data 致力于全局狀態(tài)和我們的視圖組件映射數(shù)據(jù)。
明天, 我們將開始通過操作創(chuàng)建者來觸發(fā)我們的全局狀態(tài)的更新, 并通過將多個(gè)redux模塊組合在一起來工作。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84723.html
摘要:今天我們將討論創(chuàng)建組件的最終方案,即無狀態(tài)函數(shù)的純組件。今天我們正在研究一種處理提出的復(fù)雜數(shù)據(jù)的方法,稱為體系結(jié)構(gòu)。第天部署介紹今天,我們將探討部署我們的應(yīng)用所涉及的不同部分,以便外界可以使用我們的應(yīng)用。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...
摘要:在方法中處理數(shù)據(jù)有三不同的角色派發(fā)器儲存視圖層我們的組件的主要思想是有一個(gè)單一源儲存他們只能通過觸發(fā)更新。這些操作負(fù)責(zé)調(diào)用派發(fā)器可以訂閱更改并相應(yīng)地更新自己的數(shù)據(jù)。與不同不使用派發(fā)器而是使用純函數(shù)來定義數(shù)據(jù)變異函數(shù)。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3812原文:https://www.fullstackreact...
摘要:去營救有一種方法我們把我們的歸約器分成多個(gè)歸約器每個(gè)都只負(fù)責(zé)狀態(tài)樹的葉子。此外我們還學(xué)習(xí)了如何擴(kuò)展以使用多個(gè)歸約器和動作以及多個(gè)連接的組件。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3825原文:https://www.fullstackreact.com/30-days-of-react/day-20/ 使用Redux,...
摘要:本文轉(zhuǎn)載自眾成翻譯譯者鏈接原文今天,我們在方法中使用中間件來管理我們的代碼中的復(fù)雜狀態(tài)變化。中間件是一個(gè)很好的地方。我們中間件我們將實(shí)現(xiàn)一些中間件它將代表我們處理異步請求。中間件位于動作和歸并器之間。讓我們創(chuàng)建我們的第一個(gè)中間件。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3810原文:https://www.fullsta...
摘要:包包含由團(tuán)隊(duì)提供的測試實(shí)用程序。將在一個(gè)名為的目錄中自動查找整個(gè)樹中的測試文件是的帶有下劃線。讓我們?yōu)闀r(shí)間軸組件創(chuàng)建第一個(gè)測試。其中之一是命令?,F(xiàn)在我們已經(jīng)編寫了第一個(gè)測試并確認(rèn)了我們的設(shè)置我們將在明天開始測試我們的時(shí)間軸組件。 本文轉(zhuǎn)載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...
閱讀 1343·2021-09-01 11:40
閱讀 3957·2021-08-05 10:03
閱讀 984·2019-08-30 15:54
閱讀 2826·2019-08-29 12:53
閱讀 3191·2019-08-29 12:23
閱讀 947·2019-08-26 13:45
閱讀 2288·2019-08-26 10:41
閱讀 2543·2019-08-23 16:44