90% convention, 10% library.
90%的慣例,10%的圖書館。
Redux is among the most important JavaScript libraries ever created. Inspired by prior art like Flux and Elm, Redux put JavaScript functional programming on the map by introducing a scalable architecture of three simple points.
Redux是有史以來最重要JavaScript庫之一。 受Flux和Elm等現有技術的啟發,Redux通過引入三個簡單點的可伸縮體系結構,將JavaScript函數式編程放在了地圖上。
If you're new to Redux, consider reading the official docs first.
如果您不熟悉Redux,請考慮先閱讀官方文檔 。
Redux通常是慣例 (Redux Is Mostly Convention)
Consider this simple counter application that uses the Redux architecture. If you'd like to jump ahead check out the Github repo for it.
考慮使用Redux架構的簡單計數器應用程序。 如果您想繼續前進,請查看Github存儲庫 。
國家生活在一棵樹上 (State lives in a single tree)
The application's state looks like this.
應用程序的狀態如下所示。
const initialState = { count: 0 };
動作聲明狀態更改 (Actions declare state changes)
By Redux convention, I do not directly modify (mutate) the state.
根據Redux約定, 我不直接修改(更改)狀態。
// DON'T do this in a Redux app
state.count = 1;
Instead I create all the actions the user may leverage in the application.
相反,我創建了用戶可以在應用程序中利用的所有操作。
const actions = {increment: { type: 'INCREMENT' },decrement: { type: 'DECREMENT' }
};
Reducer解釋動作并更新狀態 (Reducer interprets action and updates state)
The last architectural piece calls for a reducer, a pure function that returns a new copy of your state based on the previous state and action.
最后一個體系結構部分需要一個reducer,這是一個純函數,它根據先前的狀態和操作返回狀態的新副本。
If
increment
is fired, incrementstate.count
.如果
increment
被激發,增量state.count
。If
decrement
is fired, decrementstate.count
.如果
decrement
,則遞減state.count
。
const countReducer = (state = initialState, action) => {switch (action.type) {case actions.increment.type:return {count: state.count + 1};case actions.decrement.type:return {count: state.count - 1};default:return state;}
};
到目前為止還沒有Redux (No Redux so far)
Did you notice that we haven't touched the Redux library yet? We've just created some objects and a function. This is what I mean by "mostly convention", 90% of Redux doesn't require Redux!
您是否注意到我們還沒有涉及Redux庫? 我們剛剛創建了一些對象和一個函數。 這就是我所說的“主要是慣例”,Redux的90%不需要Redux!
讓我們實現Redux (Let's implement Redux)
To put this architecture to use, we must plug it into a store. We'll implement just one function–createStore
.
要使用此架構,我們必須將其插入商店。 我們將僅實現一個功能– createStore
。
It's used like this.
這樣使用。
import { createStore } from 'redux'const store = createStore(countReducer);store.subscribe(() => {console.log(store.getState());
});store.dispatch(actions.increment);
// logs { count: 1 }store.dispatch(actions.increment);
// logs { count: 2 }store.dispatch(actions.decrement);
// logs { count: 1 }
And here's our initial boilerplate. We'll need a list of listeners and the initial state supplied by the reducer.
這是我們最初的樣板。 我們需要一個偵聽器列表以及化簡器提供的初始狀態。
const createStore = (yourReducer) => {let listeners = [];let currentState = yourReducer(undefined, {});
}
Whenever someone subscribes to our store, they get added to the listeners
array. The is important because every time someone dispatches an action, all the listeners
must be notified in a loop.
每當有人訂閱我們的商店時,他們就會被添加到listeners
數組中。 這樣做很重要,因為每次有人分派操作時,都必須在循環中通知所有listeners
。
Calling yourReducer
with undefined
and an empty object returns the initialState
we installed up above. This gives us a proper value to return when we call store.getState()
. Speaking of which, let's create that method.
用undefined
和一個空對象調用yourReducer
返回我們在上面安裝的initialState
。 這給我們一個適當的值,當我們調用store.getState()
時可以返回。 說到這,讓我們創建該方法。
store.getState() (store.getState())
This is a function that returns the latest state from the store. We'll need this to update our UI every time the user clicks a button.
此函數可從商店返回最新狀態。 每次用戶單擊按鈕時,我們都需要用它來更新我們的UI。
const createStore = (yourReducer) => {let listeners = [];let currentState = yourReducer(undefined, {});return {getState: () => currentState};
}
store.dispatch(動作) (store.dispatch(action))
This is a function that takes an action
as a parameter. It feeds that action
and the currentState
to yourReducer
to get a new state. Then dispatch
notifies everyone subscribed to the store
.
該函數將action
作為參數。 它將該action
和currentState
饋送到yourReducer
以獲取新狀態。 然后dispatch
通知每個訂閱該store
。
const createStore = (yourReducer) => {let listeners = [];let currentState = yourReducer(undefined, {});return {getState: () => currentState,dispatch: (action) => {currentState = yourReducer(currentState, action);listeners.forEach((listener) => {listener();});}};
};
store.subscribe(偵聽器) (store.subscribe(listener))
This is a function that lets you be notified when the store receives an action It's good to use store.getState()
in here to get your latest state and update your UI.
此功能可讓您在商店收到操作時得到通知。在這里使用store.getState()
來獲取最新狀態并更新UI是很好的。
const createStore = (yourReducer) => {let listeners = [];let currentState = yourReducer(undefined, {});return {getState: () => currentState,dispatch: (action) => {currentState = yourReducer(currentState, action);listeners.forEach((listener) => {listener();});},subscribe: (newListener) => {listeners.push(newListener);const unsubscribe = () => {listeners = listeners.filter((l) => l !== newListener);};return unsubscribe;}};
};
subscribe
returns a function called unsubscribe
that you can call when you're no longer interested in listening to the store's updates.
subscribe
返回一個稱為unsubscribe
的函數,您不再對收聽商店的更新感興趣時可以調用該函數。
現在都在一起了 (All Together Now)
Let's hook this up to our buttons and view the final source code.
讓我們將其掛接到我們的按鈕上,并查看最終的源代碼。
// simplified createStore function
const createStore = (yourReducer) => {let listeners = [];let currentState = yourReducer(undefined, {});return {getState: () => currentState,dispatch: (action) => {currentState = yourReducer(currentState, action);listeners.forEach((listener) => {listener();});},subscribe: (newListener) => {listeners.push(newListener);const unsubscribe = () => {listeners = listeners.filter((l) => l !== newListener);};return unsubscribe;}};
};// Redux architecture pieces
const initialState = { count: 0 };const actions = {increment: { type: 'INCREMENT' },decrement: { type: 'DECREMENT' }
};const countReducer = (state = initialState, action) => {switch (action.type) {case actions.increment.type:return {count: state.count + 1};case actions.decrement.type:return {count: state.count - 1};default:return state;}
};const store = createStore(countReducer);// DOM elements
const incrementButton = document.querySelector('.increment');
const decrementButton = document.querySelector('.decrement');// Wire click events to actions
incrementButton.addEventListener('click', () => {store.dispatch(actions.increment);
});decrementButton.addEventListener('click', () => {store.dispatch(actions.decrement);
});// Initialize UI display
const counterDisplay = document.querySelector('h1');
counterDisplay.innerHTML = parseInt(initialState.count);// Update UI when an action fires
store.subscribe(() => {const state = store.getState();counterDisplay.innerHTML = parseInt(state.count);
});
And once again here's our final UI.
這又是我們的最終用戶界面。
If you're interested in the HTML/CSS I used, here's the GitHub repo again!
如果您對我使用HTML / CSS感興趣,請再次訪問GitHub存儲庫 !
需要免費輔導嗎? (Want Free Coaching?)
If you'd like to schedule a free call to discuss Front-End development questions regarding code, interviews, career, or anything else follow me on Twitter and DM me.
如果您想安排免費電話討論有關代碼,面試,職業或其他方面的前端開發問題,請在Twitter和DM me上關注我 。
After that if you enjoy our first meeting, we can discuss an ongoing coaching to help you reach your Front-End development goals!
之后,如果您喜歡我們的第一次會議,我們可以討論一個持續的教練,以幫助您實現前端開發目標!
貢獻您的力量 (Wear Your Contributions)
If you're coding every day, especially if you're committing to GitHub, wouldn't it be cool to wear that contribution map for all to see?
如果您每天都在編寫代碼,特別是如果您要提交到GitHub,那么穿上所有人都能看到的貢獻圖會不會很酷?
Gitmerch.com lets you print a t-shirt of your GitHub contribution map! Use the code, Yazeed, at checkout for a discount.
Gitmerch.com可讓您打印GitHub貢獻圖的T恤! 結帳時使用代碼Yazeed可獲得折扣。
謝謝閱讀 (Thanks for reading)
For more content like this, check out https://yazeedb.com!
有關更多內容,請訪問https://yazeedb.com!
Until next time!
直到下一次!
翻譯自: https://www.freecodecamp.org/news/redux-in-24-lines-of-code/