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
댓글 없음:
댓글 쓰기