Redux 이해
아래 2개의 글 정도면 대략적인 이해가 가능할 듯 하다.Redux 사용
- Store 만들기 : store 를 만들고
var store = Redux.createStore(...) - reducer 등록 : 이 store 의 state 를 변경하는데 사용되는 함수(reducer 라고 부른다.) 를 인자로 넘겨준다.
var store = Redux.createStore(counter) // counter is function - listener 등록 : 그리고 이 state 가 변경될 때 마다 호출되는 함수인 listener 를 listener 에 등록을 한다. subscribe 을 이용하면 된다.
store.subscribe(render) // render is function - dispatch(event 발생)
- reducer : store 에서 dispatch 를 실행하면 위에서 등록한 reducer 를 실행하게 된다.
store.dispatch({ type: 'INCREMENT' }) - listener : reducer 의 실행이 끝나면 등록된 listener 들을 실행시킨다.
for (var i = 0; i < listeners.length; i++) {
listeners[i]();
}
combineReducers()[ref. 3]
이녀석은 여러 reducer, 즉 state tree 가 여러개 여서, reducer 가 여러개 인 경우에 사용하기 위한 녀석이다.
이녀석에 대해 이야기 하기 전에 미리 알아야 할 점은 Redux code 의 store.dispatch 부분이다.
이 dispatch 에서는 단 한개의 reducer(currentReducer) 만을 호출한다. 그러므로 만약 우리가 여러개의 state tree 를 가지고 있어서 여러개의 reducer 를 호출해야 한다면, redux 를 사용할 수 없다.
그래서 Redux 에서는 이런 경우에 여러 "특정 state tree" 에 대해 "특정 state reducer" 를 호출해주는 함수를 등록해서 사용하도록 하고 있다.
그래서 Redux 에서는 combineReducers 라는 helper 함수를 제공한다.
이녀석은 아래처럼 사용한다.
combineReducers({ todos: myTodosReducer,
counter: myCounterReducer })
좀 더 긴 code 를 봐보자.
let previousState = {
counter: 'SHOW_ALL',
todos: [
{
text: 'Read the docs.',
complete: false
}
]
}
let action = {type : "ACTION_ADD_TODO"}
let topReducer = combineReducers({ todos: myTodosReducer,
counter: myCounterReducer })
var store = Redux.createStore(topReducer )
let nextState = store.dispatch(previousState, action)
위의 code 같은 경우라면 combinReducers 내부는 아래처럼 동작할 것이다.(실제 code 는 다르지만, 아래와 같은 결과를 가져다 준다.)
return{
todos : myTodosReducer(state.todos, action)
counter : myCounterReducer (state.counter, action)
}
이건 간단하게 생각하면, store (reducer 를 하나만 호출하는)에 reducer 를 등록하는 방법이라고 생각하면 된다. event 가 발생할 때마다, 해당하는 모든reducer 를 불러줘야 하는데, reducer 를 하나만 호출하도록 Redux 가 구성되어 있어서, 추가적으로 state 에 따라 reducer 를 분배할 수 있도록 combineReducer 를 만든 것이라고 생각하면 된다.
이 경우에 주의할 점은 reducer 에서 당연히 자신들이 다룰 수 있는 state 외의 값이 올 때에 대한 처리도 해놔야 한다.
이 경우에 주의할 점은 reducer 에서 당연히 자신들이 다룰 수 있는 state 외의 값이 올 때에 대한 처리도 해놔야 한다.
Redux source flow
아래 소스를 직접 실행해 보고 싶다면 ref. 2 를 참고하자.
//reducer
function counter(state, action) {
if (typeof state === 'undefined') {
return 0
}
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
function render() {
valueEl.innerHTML = store.getState().toString()
}
var store = Redux.createStore(counter)
function createStore(reducer, preloadedState, enhancer) {
var _ref2;
...
var currentReducer = reducer;
var currentState = preloadedState;
var currentListeners = [];
var nextListeners = currentListeners;
var isDispatching = false;
...
dispatch({ type: ActionTypes.INIT });
return _ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}, _ref2[_symbolObservable2['default']] = observable, _ref2;
// subscribe
store.subscribe(render);
function subscribe(listener) {
...
var isSubscribed = true;
ensureCanMutateNextListeners();
nextListeners.push(listener);
// How to unsubscribe
// var unsubscribe = store.subscribe(render);
// unsubscribe()
return function unsubscribe() {
if (!isSubscribed) {
return;
}
isSubscribed = false;
ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
};
}
// dispatch event
store.dispatch({ type: 'INCREMENT' })
function dispatch(action) {
...
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}
var listeners = currentListeners = nextListeners;
for (var i = 0; i < listeners.length; i++) {
listeners[i]();
}
return action;
}
react-redux 사용
See Also
Reference
- Examples · Redux
- redux/src at master · reactjs/redux : redux sources
- Data Flow · Redux

댓글 없음:
댓글 쓰기