컴포넌트에서 상태 변경을 요청해야 하는 경우가 발생한다.
컴포넌트는 Store의 메서드 중 하나인 dispatch()
를 호출한다.
dispatch()
는 Store에 상태를 변경해달라고 요청한다.
3-1. Store는 상태를 변경할테니 참고할 내용을 보내달라고 한다.
3-2. 이 때 dispatch()
의 인자로 action 함수를 담아서 보낸다. (콜백 함수)
3-3. action 함수(action creator)는 Store가 참고할 내용(type, payload)을 내뱉는 함수다.
참고할 내용을 전달받은 Store는 자신이 직접 상태를 변경하지 않고, Store 내부에 있는 Reducer 함수를 통해 상태를 변경한다.
4-1. 이 때 Reducer는 변경 전 상태와 action이 내뱉은 참고 내용(객체)을 인자로 받고, 새로운 상태를 내뱉는다.
const Reducer = (state, action) => {
return {
...state, // 기존 state
user: [...state.user, action.payload], // 변경되는 State 일부분
};
}
Reducer가 상태 변경을 완료하면, Store는 변경된 상태를 받아 기존 상태를 변경된 상태로 갈아끼운다.
5-1. 이 때 중요한 사실은 단순 덮어쓰기가 아니라 Spread 연산자를 통해 아예 참조값이 다른 상태로 변경한다는 것이다. 왜냐하면, Redux는 그저 데이터만 변경되는 때가 아니라 참조값이 변경되어야 상태가 변경되었다고 인식하기 때문이다.
상태 변경이 모두 완료되면, 아까 상태 변경을 요청한 컴포넌트에 상태가 변경되었음을 알린다.
해당 컴포넌트 리렌더링
export const LOGIN_USER = "login_user";
export const LOGOUT_USER = "logout_user";
export function logoutUser() {
...
return {
type: LOGOUT_USER,
payload: data,
};
}
초기 상태는 불변성을 유지한다.
const UserReducer = (state, action) => {
switch (action.type) {
case LOGIN_USER:
return { ...state, loginSuccess: action.payload };
case LOGOUT_USER:
return { ...state };
default:
return state;
}
};
const rootReducer = combineReducers({
user,
});
(index.js)
const store = createStore(rootReducer)
(index.js)
root.render(
<Provider store={store}>
<App />
</Provider>
);