Redux初学者指南
by Safeer Hayat
通過更安全的哈亞特
Understanding Redux as a beginner can be quite confusing. Redux has an abundance of new terms and concepts which are often pretty unintuitive. This guide presents a very simplified example of a Redux implementation. I will define each of the steps and terms in a way that makes sense to a complete beginner.
將Redux理解為初學(xué)者可能會造成很大的困惑。 Redux有很多新術(shù)語和新概念,這些新術(shù)語和新概念通常很不直觀。 本指南提供了Redux實現(xiàn)的非常簡化的示例。 我將以適合初學(xué)者的方式定義每個步驟和術(shù)語。
This is intended to be a guide to demystify Redux elements. It does not contain the most technically accurate definitions. It does not have the best ever practices. It does have definitions that will help develop an understanding for someone with no prior knowledge of these concepts. There is a simple implementation as to not confuse with unnecessary details.
這旨在作為使Redux元素神秘化的指南。 它不包含技術(shù)上最準(zhǔn)確的定義。 它沒有最佳實踐。 它確實具有一些定義,這些定義將有助于對以前不了解這些概念的人有所了解。 有一個簡單的實現(xiàn)方式,可以與不必要的細(xì)節(jié)混淆。
The example we will run through in this guide will be a simple todo app. The app allows a user to add or remove todo items and see them displayed on the page.
我們將在本指南中運(yùn)行的示例是一個簡單的待辦應(yīng)用程序。 該應(yīng)用程序允許用戶添加或刪除待辦事項,并在頁面上顯示它們。
I will run through step by step each element of Redux, explaining what that element is and how to implement it with code examples. Scroll to the bottom to see the full code example which will show how it all fits together as a complete React app.
我將逐步介紹Redux的每個元素,說明該元素是什么以及如何通過代碼示例實現(xiàn)它。 滾動到底部以查看完整的代碼示例,該示例將顯示如何將它們?nèi)拷M合成一個完整的React應(yīng)用程序。
步驟摘要 (Steps Summary)
腳步 (Steps)
1.編寫減速器功能 (1. Write the reducer function)
The reducer function is a function which tells the store how to respond to actions. The function returns the new and updated state whenever an action is dispatched. State is immutable (can’t be changed) so the reducer always returns a new state. The reducer usually uses the spread operator to insert the current state into a new object/array and appending to it. Common practice is to use a switch/case statement and check the type property of the action passed in. Then write the code that updates the state for each case.
減速器功能是告訴商店如何響應(yīng)動作的功能。 每當(dāng)分派操作時,該函數(shù)都會返回新狀態(tài)和更新狀態(tài)。 狀態(tài)是不可變的(無法更改),因此減速器始終返回新狀態(tài)。 精簡器通常使用散布運(yùn)算符將當(dāng)前狀態(tài)插入到新的對象/數(shù)組中并追加到該對象/數(shù)組中。 通常的做法是使用switch / case語句并檢查傳入的操作的type屬性。然后編寫更新每種情況的狀態(tài)的代碼。
We write our reducer function first because we will need to pass this when we instantiate our store. To understand what’s happening though requires some knowledge of actions and dispatch. We will cover this further on in this guide.
我們首先編寫reducer函數(shù),因為在實例化商店時我們將需要傳遞它。 要了解正在發(fā)生的事情,需要對操作和調(diào)度有一定的了解。 我們將在本指南中對此進(jìn)行進(jìn)一步介紹。
For now know that our todo app will need to interact with the store in 2 ways: to add a new todo item to the state and to remove a todo item from the state. Therefore we write our function so that it responds to 2 cases of the action type. It uses the action value to either add or remove a todo item from the state.
現(xiàn)在,我們的待辦事項應(yīng)用程序?qū)⑿枰ㄟ^兩種方式與商店交互:將新的待辦事項添加到州,并從州中刪除待辦事項。 因此,我們編寫函數(shù)以使其能夠響應(yīng)2種情況的動作類型。 它使用操作值在狀態(tài)中添加或刪除待辦事項。
The reducer is passed 2 parameters: state (this is the entire state currently in the store, and we give it a default value if state does not exist yet) and the action. We return the state in the default case.
reducer傳遞了2個參數(shù):狀態(tài)(這是商店中當(dāng)前的整個狀態(tài),如果狀態(tài)不存在,則為它提供默認(rèn)值)和操作。 我們以默認(rèn)情況返回狀態(tài)。
2.實例化根組件中的存儲 (2. Instantiate the store in the root component)
The store is the thing which actually contains the state in it. It’s a bit magical and you don’t really need to know the ins and outs of it. All you need to know is that you don’t access it directly like you would a normal React state. You access it and make changes to it using reducers, actions and dispatch.
商店實際上就是其中包含狀態(tài)的事物。 這有點神奇,您實際上不需要了解它的來龍去脈。 您需要知道的是,您不會像正常的React狀態(tài)那樣直接訪問它。 您可以訪問它并使用化簡器,操作和調(diào)度對其進(jìn)行更改。
The other important thing to know about the store is that it contains some useful and important methods. The main method is the dispatch function. It also contains a getState method (for viewing the state) and subscribe method (runs a callback every time an action is dispatched).
關(guān)于商店的另一件重要的事情是它包含一些有用且重要的方法。 主要方法是調(diào)度功能。 它還包含getState方法(用于查看狀態(tài))和subscription方法(每次分派操作時運(yùn)行回調(diào))。
The store is typically instantiated at the root of your app (e.g. App.js). It is stored as a variable and has the reducer passed in as a parameter. The store is then passed in as a prop to the Provider component.
該商店通常在應(yīng)用程序的根目錄(例如App.js)上實例化。 它存儲為變量,并將減速器作為參數(shù)傳遞。 然后將商店作為道具傳遞給提供程序組件。
We instantiate our store object passing in the reducer we just created.
我們實例化傳入剛剛創(chuàng)建的化簡器的商店對象。
3.用<Provider>組件包裝組件,將其作為道具傳入商店 (3. Wrap the components with the <Provider> component, passing in the store as a prop)
The Provider is a component created to make it easier to pass the store to all your components. The Provider component wraps around all your components (e.g. render your components as children of Provider). You pass the store in as a prop to the Provider only. This means you don’t need to pass in the store as a prop to every component as each component gets it from the Provider. However, this doesn’t mean the components have access to the state yet. You still need to use the mapStateToProps (we will cover this later) to have the state accessible in your component.
提供程序是一個創(chuàng)建的組件,它使將商店傳遞給所有組件變得更加容易。 Provider組件包裝了所有組件(例如,將組件渲染為Provider的子代)。 您只能將商店作為道具傳遞給提供者。 這意味著您不需要將存儲作為每個組件的道具傳遞,因為每個組件都可以從提供者那里獲取。 但是,這并不意味著組件還可以訪問狀態(tài)。 您仍然需要使用mapStateToProps(我們將在以后進(jìn)行介紹)以使?fàn)顟B(tài)可在組件中訪問。
We wrap the Todo component we are going to make with our Provider component. We pass in the store we created in the previous step.
我們使用Provider組件包裝要制作的Todo組件。 我們傳入在上一步中創(chuàng)建的商店。
4.編寫組件 (4. Write the component)
Next, we begin to write the Todo component which will render the todo items and interact with the Redux store.
接下來,我們開始編寫Todo組件,該組件將渲染待辦事項并與Redux商店進(jìn)行交互。
The component is a stateful component containing one state element to keep track of what the user has typed into the input. We have a function called handleChange. This function updates the state every time the user types anything into the input. So far this is all we will write. We need to understand more about Redux before we can write the logic. The logic will add new todos to the state and retrieve current ones from the state to render on the page.
該組件是一個有狀態(tài)的組件,其中包含一個狀態(tài)元素,以跟蹤用戶在輸入中鍵入了什么。 我們有一個稱為handleChange的函數(shù)。 每當(dāng)用戶在輸入中輸入任何內(nèi)容時,此功能都會更新狀態(tài)。 到目前為止,這就是我們要寫的全部內(nèi)容。 在編寫邏輯之前,我們需要了解有關(guān)Redux的更多信息。 邏輯將向狀態(tài)添加新的待辦事項,并從狀態(tài)中檢索當(dāng)前待辦事項以呈現(xiàn)在頁面上。
5.定義動作 (5. Define the actions)
An action is a simple object containing a property called ‘type’. This object is passed into the dispatch function. It is used to tell the store what event has just occurred (by reading the actions type property). It also tells what update it should make to the state in response (through the reducer function). The action can also contain other properties for any other data you want to pass into the reducer. Data can only be passed through here so any data needed will need to be passed in here.
動作是一個簡單的對象,其中包含一個稱為“類型”的屬性。 該對象傳遞到調(diào)度函數(shù)中。 它用于告訴商店剛剛發(fā)生了什么事件(通過讀取action type屬性)。 它還告訴響應(yīng)狀態(tài)(通過reducer函數(shù))應(yīng)對狀態(tài)進(jìn)行哪些更新。 該操作還可以包含要傳遞給化簡器的任何其他數(shù)據(jù)的其他屬性。 數(shù)據(jù)只能在此處傳遞,因此所需的任何數(shù)據(jù)都需要在此處傳遞。
We will use action creators to define our actions. Action creators are a function which returns the action object. Its purpose is to make the action more portable and testable. It doesn’t change the behavior of how anything works. It’s another method of writing and passing the action. It also allows you to pass in parameters if you want to send data with the action which we will be doing. So we require to use action creators here.
我們將使用動作創(chuàng)建者來定義我們的動作。 動作創(chuàng)建者是一個返回動作對象的函數(shù)。 其目的是使操作更具可移植性和可測試性。 它不會改變?nèi)魏问挛锏男袨椤?這是編寫和傳遞動作的另一種方法。 如果您想通過我們將要執(zhí)行的操作發(fā)送數(shù)據(jù),它還允許您傳遞參數(shù)。 因此,我們需要在此處使用動作創(chuàng)建者。
If you remember our reducer responded to 2 action types — “ADD_TODO” and “REMOVE_TODO”. We will define those actions with our action creators. In our add_todo action will return “ADD_TODO” as the type and the todo item we want to add to the store as the value (we need the store to add this todo item to the state so it gets passed in here). In the remove_todo we return “REMOVE_TODO” as the type and the index of the todo item in the store as the value. We’ll need this to remove it from the list of todos.
如果您還記得,我們的減速器對兩種動作類型進(jìn)行了響應(yīng)-“ ADD_TODO”和“ REMOVE_TODO”。 我們將與動作創(chuàng)建者一起定義這些動作。 在我們的add_todo操作中,將返回“ ADD_TODO”作為類型,并返回要添加到存儲中的待辦事項作為值(我們需要商店將此待辦事項添加到狀態(tài),以便它在此處傳遞)。 在remove_todo中,我們返回“ REMOVE_TODO”作為類型,并返回商店中待辦事項的索引作為值。 我們需要此功能將其從待辦事項列表中刪除。
If you return to our reducer function definition hopefully it now makes more sense. By reading the action.type the reducer knows whether it needs to add a todo to the state or remove one from it. It has the todo item passed in the add_todo. It appends to the current state using the spread operator. In the remove_todo it uses the spread operator to create a new array appending the current state sliced twice, once with all the elements before the one to remove and second with all the elements after the one to remove, thus creating our new state object with the todo item removed.
如果您希望返回我們的化簡函數(shù)定義,那么現(xiàn)在更有意義了。 通過讀取action.type,reducer知道它是否需要向狀態(tài)添加待辦事項或從狀態(tài)中刪除一個待辦事項。 它在add_todo中傳遞了待辦事項。 使用擴(kuò)展運(yùn)算符將其附加到當(dāng)前狀態(tài)。 在remove_todo中,它使用spread運(yùn)算符創(chuàng)建一個新的數(shù)組,該數(shù)組將切成兩次的當(dāng)前狀態(tài)附加到切片中,一次刪除所有元素,然后刪除所有元素,從而創(chuàng)建一個新的狀態(tài)對象,其中待辦事項已刪除。
However, this still isn’t a complete picture. We have not yet covered how the reducer gets called and passed in the right action. For that, we will need to move on to define our dispatch function.
但是,這還不是完整的圖片。 我們尚未介紹在正確的操作中如何調(diào)用和傳遞reducer。 為此,我們將繼續(xù)定義調(diào)度功能。
6.定義調(diào)度,將它們附加到將觸發(fā)調(diào)度的位置(即事件偵聽器等) (6. Define the dispatch, attach these to where the dispatches will be triggered (ie event listeners etc))
The dispatch function is a method of the store which is used to trigger a change in the state. Any event or anything which needs to update the state must call the dispatch method to do so. This is the only way to trigger a change/update to the state. Dispatch is called and the action object is passed in (or the action creator if that was used). Once a dispatch is triggered the store then calls the reducer function and passes in the action that the dispatch provided which updates the state, as we’ve seen earlier.
調(diào)度功能是存儲的一種方法,用于觸發(fā)狀態(tài)更改。 任何事件或任何需要更新狀態(tài)的事物都必須調(diào)用dispatch方法來執(zhí)行。 這是觸發(fā)狀態(tài)更改/更新的唯一方法。 調(diào)用Dispatch并傳遞操作對象(或使用操作創(chuàng)建者)。 一旦觸發(fā)了調(diào)度,商店便會調(diào)用reducer函數(shù),并傳遞調(diào)度所提供的操作來更新狀態(tài),如前所述。
Below we define the bottom half of our Components render method. We create our buttons which will contain our event handlers. Inside those, we will define our dispatch functions.
在下面,我們定義了組件渲染方法的下半部分。 我們創(chuàng)建包含事件處理程序的按鈕。 在這些內(nèi)部,我們將定義我們的調(diào)度功能。
The first button is a simple add button. This button will dispatch the add_todo action to the store. It will pass in the current user input as the value (this is the todo item that the reducer appends to the new state). Note we call dispatch as this.props.dispatch. It’s a bit out of the scope of this guide to understand how and why this gets passed as a prop to the component. So just know that it does and we can call it like this.
第一個按鈕是一個簡單的添加按鈕。 此按鈕將將add_todo操作調(diào)度到商店。 它將作為值傳遞當(dāng)前用戶輸入(這是化簡器附加到新狀態(tài)的待辦事項)。 注意,我們將調(diào)度稱為this.props.dispatch 。 了解如何以及為什么將它作為道具傳遞給組件超出了本指南的范圍。 因此,只要知道它確實可以,我們就可以這樣稱呼它。
The second event handler is written as an onClick on our rendered todo item. By clicking on any todo item on the page it triggers an event handler. The event handler searches the list of todos and finds the index of that todo in the list. It then dispatches the remove_todo action and passes in the index.
第二個事件處理程序被編寫為渲染的待辦事項上的onClick。 通過單擊頁面上的任何待辦事項,它會觸發(fā)事件處理程序。 事件處理程序搜索待辦事項列表,并在列表中找到該待辦事項的索引。 然后,它調(diào)度remove_todo操作并傳遞索引。
The cycle for how to update the state in the Redux store is now fully defined. We know that any time we want to change the state we need to call the dispatch method, pass in the appropriate action, and ensure our reducer handles those actions and returns the new state using any values we passed in via the action.
現(xiàn)在已完全定義了如何在Redux存儲中更新狀態(tài)的周期。 我們知道,每當(dāng)要更改狀態(tài)時,我們都需要調(diào)用dispatch方法,傳遞適當(dāng)?shù)牟僮?#xff0c;并確保我們的reducer處理這些操作并使用通過操作傳遞的任何值返回新狀態(tài)。
The only puzzle piece missing now is how do we get the state from the Redux store. You’ve probably noticed that I’ve mapped over a list called this.props.todos in the previous example. You may be wondering where that came from. You may also recall at the beginning of this guide I mentioned that passing store into the Provider component is not enough to gain access to the state in the store. This is all addressed in the next 2 steps as we define our mapStateToProps function and pass that into the connect function.
現(xiàn)在唯一缺少的難題是如何從Redux商店獲取狀態(tài)。 您可能已經(jīng)注意到,在上一個示例中,我已映射到名為this.props.todos的列表上。 您可能想知道那是哪里來的。 您可能還記得在本指南的開頭我提到過,將存儲傳遞到Provider組件不足以獲取對存儲中狀態(tài)的訪問。 在定義我們的mapStateToProps函數(shù)并將其傳遞給connect函數(shù)時,將在接下來的2個步驟中解決所有問題。
7.定義mapStateToProps函數(shù) (7. Define the mapStateToProps function)
When you want your component to have access to the state you have to explicitly specify what in the state the component will get access to. Your component will not have access to state without this.
當(dāng)您希望組件可以訪問狀態(tài)時,必須明確指定組件可以訪問的狀態(tài)。 否則,您的組件將無法訪問狀態(tài)。
mapStateToProps is a function which simply returns an object that defines what state should be passed into the component by assigning values in the state to properties you define in this object. Essentially, the object you return in the mapStateToProps is what your props will be in your component. The mapStateToProps function is passed into the connect method as the first argument.
mapStateToProps是一個函數(shù),它簡單地返回一個對象,該對象通過將狀態(tài)中的值分配給在此對象中定義的屬性來定義應(yīng)將什么狀態(tài)傳遞到組件中。 本質(zhì)上,您在mapStateToProps中返回的對象就是您的prop將在組件中的內(nèi)容。 mapStateToProps函數(shù)作為第一個參數(shù)傳遞到connect方法中。
The mapStateToProps takes the entire state as a parameter and you take only what you need from it. Here though as our state only contains the list of todos. We need that list in our ToDo component, we will return the entire state as a property called todos.
mapStateToProps將整個狀態(tài)作為參數(shù),而您只需要它所需要的。 盡管這里我們的州只包含待辦事項清單。 我們需要在T??oDo組件中使用該列表,然后將整個狀態(tài)作為名為todos的屬性返回。
As you can see now, we have access to our entire todos list in our props as this.props.todos. This is how we were able to render all our todos in the previous example by mapping over it.
如您現(xiàn)在所見,我們可以在道具中以this.props.todos訪問整個this.props.todos列表。 這就是我們能夠通過映射上一個示例來渲染所有待辦事項的方式。
Finally we need to pass this function into our connect method to connect everything together.
最后,我們需要將此函數(shù)傳遞到connect方法中,以將所有內(nèi)容連接在一起。
8.導(dǎo)出connect函數(shù),傳入mapStateToProps和null作為2個參數(shù),并在第二對括號中傳遞組件名稱 (8. Export the connect function, passing in mapStateToProps and null as the 2 arguments and passing the component name in the second pair of brackets)
Connect is a method that hooks up mapStateToProps and mapDispatchToProps (see below) functions to your component so that the store can read those functions and ensure what you defined in there gets passed into the component as props. This method has a special syntax which looks like this:
Connect是一種將mapStateToProps和mapDispatchToProps函數(shù)(請參見下文)連接到您的組件的方法,以便商店可以讀取這些函數(shù)并確保您在其中定義的內(nèi)容作為prop傳遞到組件中。 此方法具有特殊的語法,如下所示:
connect(mapStateToProps, MapDispatchToProps)(YourComponent)
connect(mapStateToProps, MapDispatchToProps)(YourComponent)
You pass in the 2 map...ToProps functions to the connect and then the name of your component inside the second pair of brackets. A typical pattern is to export the connect method instead of your component when you are exporting your component at the end of your file. For example:
您將2 map...ToProps函數(shù)傳遞給connect,然后在第二對括號內(nèi)傳遞組件名稱。 一種典型的模式是在文件末尾導(dǎo)出組件時,導(dǎo)出connect方法而不是組件。 例如:
export default connect(mapStateToProps, MapDispatchToProps)(YourComponent)
export default connect(mapStateToProps, MapDispatchToProps)(YourComponent)
This then acts in the same way as exporting normally except the state and dispatches will be passed in as props. mapStateToProps and mapDispatchToProps are actually optional params to connect. If you don’t want to pass one or either, put null in their place instead.
然后,它的行為與正常導(dǎo)出的行為相同,除了狀態(tài)和調(diào)度將作為道具傳遞。 mapStateToProps和mapDispatchToProps實際上是要連接的可選參數(shù)。 如果您不想傳遞一個或兩個,則將null代替。
You may be wondering where this mapDispatchToProps function has come from and why we haven’t mentioned it anywhere before here. Well, as this guide is the most simplified example of a Redux store and mapDispatchToProps isn’t strictly mandatory, I haven’t included it in our example. If you don’t pass mapDispatchToProps and pass null instead then you can still access the dispatch function in your component as we have earlier as this.props.dispatch.
您可能想知道m(xù)apDispatchToProps函數(shù)的來源以及為什么我們在此之前未提及它。 好吧,由于本指南是Redux存儲的最簡化示例,并且mapDispatchToProps不是嚴(yán)格必需的,因此我沒有在示例中包含它。 如果您不傳遞mapDispatchToProps并傳遞null,那么您仍然可以訪問組件中的dispatch函數(shù),就像我們之前的this.props.dispatch 。
So to finish off our example app, all we have to do is export our component wrapping it with the connect function and passing in the mapStateToProps we just defined.
因此,要完成示例應(yīng)用程序,我們要做的就是導(dǎo)出使用connect函數(shù)將其包裝的組件,并傳入剛剛定義的mapStateToProps。
And that’s it! That’s a complete implementation of a Redux store. See below for the working example of what we implemented.
就是這樣! 這是Redux存儲的完整實現(xiàn)。 請參閱以下有關(guān)我們實施的工作示例。
完整注釋的代碼示例 (Full Annotated Code Example)
App.js
App.js
Todo.js
Todo.js
I hope that this guide can simplify some of the strange and sometimes confusing details of Redux. It’s not a complete guide of Redux, as there are definitely more elements and patterns to understand. But if you can understand this guide then you are well on your way to being able to work with and install Redux in your apps.
我希望本指南可以簡化Redux的一些奇怪的,有時令人困惑的細(xì)節(jié)。 它不是Redux的完整指南,因為肯定還有更多的元素和模式需要理解。 但是,如果您能理解本指南,那么您就可以很好地使用Redux并在您的應(yīng)用程序中安裝Redux。
翻譯自: https://www.freecodecamp.org/news/a-beginners-guide-to-redux-9f652cbdc519/
總結(jié)
以上是生活随笔為你收集整理的Redux初学者指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到妹妹出车祸死了是什么意思
- 下一篇: webassembly_WebAssem