index.js
import { createStore, actionCreator } from "./redux";
const INIT = "init";
const INCREMENT = "increment";
const RESET = "reset";
function reducer(state = {}, { type, payload }) {
switch (type) {
case INIT: {
return {
...state,
count: payload.count,
};
}
case INCREMENT:
return { ...state, count: state.count ? state.count + 1 : 1 };
case RESET:
return {
...state,
count: 0,
};
default:
return { ...state };
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * *
* 헬퍼 함수 *
* init : store의 값을 count로 초기화 *
* increment : store의 count를 1증가 또는 1로 설정 *
* reset : store의 count를 0으로 초기화 *
* * * * * * * * * * * * * * * * * * * * * * * * * */
function init(count) {
store.dispatch(actionCreator(INIT, { count }));
}
function increment() {
store.dispatch(actionCreator(INCREMENT));
}
function reset() {
store.dispatch(actionCreator(RESET));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 스토어의 생성 및 subscribe를 사용한 state 로깅 *
* 1. createStore 함수로 스토어를 생성 *
* 2. getState 함수를 사용해 값을 출력하는 함수 작성 *
* 3. 스토어의 subscribe 메서드를 이용해 2번에서 작성한 함수로 구독 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const store = createStore(reducer);
function update() {
console.log(store.getState());
}
store.subscribe(update);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 스토어의 값을 변경하는 액션을 실행시키는 방법 *
* 1. type과 payload을 포함한 액션을 dispatch *
* 2. action을 반환하는 actionCreator 헬퍼 함수를 사용한 후 dispatch *
* 3. payload를 전달받아 dispatch까지 해주는 헬퍼 함수 이용 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
store.dispatch({ type: INCREMENT }); // { count: 1 }
store.dispatch(actionCreator(INCREMENT)); // { count: 2 }
increment(); // { count: 3 }
store.dispatch({ type: INIT, payload: { count: 5 } }); // { count: 5 }
store.dispatch(actionCreator(INIT, { count: 0 })); // { count: 0 }
init(10); // { count: 10 }
store.dispatch({ type: RESET }); // { count: 0 }
store.dispatch(actionCreator(RESET)); // { count: 0 }
reset(0); // { count: 0 }
redux.js
// 스토어 만드는 함수
export function createStore(reducer) {
let state;
const listener = [];
const publish = () => {
listener.forEach(({ subscriber, context }) => {
subscriber.call(context);
});
};
const dispatch = (action) => {
state = reducer(state, action);
publish();
};
const subscribe = (subscriber, context = null) => {
listener.push({ subscriber, context });
};
const getState = () => ({ ...state });
return {
getState,
dispatch,
subscribe,
};
}
// 액션생성함수
export function actionCreator(type, payload = {}) {
return {
type,
payload: { ...payload },
};
}
action
: 상태 변화가필요할 때 객체의 형태로 발생시킴. type
필드는 필수적으로 가지고 있어야하고 추가적으로 다른 필드도 가질 수 있다.
{ type: 'increment' }
or
{
type: 'increment',
text: '증가'
}
action 생성함수
: 액션을 만드는 함수. 액션 객체를 만들 때 필요한 데이터를 인자로 받아 액션 객체를 만들어 리턴해주는 함수.
// 화살표 함수로도 만들 수 있음
const createAction = text => ({
type: 'increment',
text
});
store
: createStore 함수를 통해 만들 수 있다. state에 직접 접근하지 못하도록 클로저를 이용하기 때문에 상태를 보려면 getState 함수를 통해야 한다.
reducer
: 현재의 상태와 전달받은 액션을 통해 새로운 상태를 만들어서 store에 저장한다. store에 있는 state는 반드시 reducer를 통해서 변경되어야 한다.
dispatch
: store의 내장함수 중 하나이다. 액션을 파라미터로 전달하면서 호출을 하면 스토어는 리듀서 함수를 실행시켜서 해당 액션을 참고하여 새로운 상태를 만든다.
subscribe
: store의 내장 함수 중 하나. 함수 형태의 값을 파라미터로 받고, 액션이 디스패치 되었을 때마다 전달받은 함수를 호출한다
(참고: Redux (1) 소개 및 개념정리)