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/