Let's imagine that we have a component, a simple counter. The counter has a state and two buttons to manipulate with this state. We also have a function to render the state.
And here we have two problems:
To solve these problems we will use the FLUX approach which essentially means "Data down, Action up". Clicking any button will trigger action. So we have an action and now we need to change the state of our application. But how we suppose to do that?
Redux is about functional programming, so we will use pure functions and immutability. Functions, that will change our state we will call reducer. It will get the current state and action as an argument and will return to the new state. The function will look like this:
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
Now we need to create our store. Let's right the new function and call it
createStore
. function createStore(reducer) {
let state = 0;
return {
getState(){
return state;
},
dispatch(action){
state = reducer(state, action);
}
}
}
Before we can move on, it's better to know what does observer pattern does. Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing. Let's add this logic to our function:
function createStore(reducer) {
let state = 0;
const observers = [];
return {
getState(){
return state;
},
subscribe(observer){
observers.push(observer);
},
dispatch(action){
state = reducer(state, action);
observers.forEach(cb => cb());
}
}
}
And that's it! We separate representation and data layer, move the state from component to separate place, dependencies now have on direction, data down and actions up.