Redux란?
상태 관리 라이브러리로 Component별로 props/state를 바꿔주는 복잡한 관계를 redux 하나로 외부에서 state들을 공용으로 관리하여 가져다 쓸 수 있다.
1. State(상태)
State란 React Component 내에서 사용되는 데이터 집합을 말하며 이 상태 정보를 가지고 컴포넌트의 속성을 바꾸거나 어떤 event가 일어났을 경우 상태 값을 변경하여 Component를 변경된 상태로 렌더링할 수 있다.
이런 State를 변경하는 것이 (Action)이며 Action과 Store를 연결해주는 스토어 관리자가 (Dispatcher)다.
Store는 State를 관리하는 저장소로 State는 다음과 같이 객체 형식으로 사용한다. 객체 내에서 카테고리 별로 관리가 가능하다.
const initialState = {
Data : {
groupData : [],
roomData : [],
connectInfoData : [], // {room id, user id, leave time, connecting}
},
ListState : {
groupStates : [],
groupOpenStates : [],
roomSelectedStates : [],
unreadMesssageStates : [], // {room id , message count}
}
};
2. Action
Action은 상태 변경을 일으키는 이벤트에 대한 정적 정보다.
Action은 Reducer가 구분할 수 있도록 액션 타입과 데이터를 가진 객체 형식이다. 아래와 같이 reducer에 있는 액션 타입들을 받아와 외부에서도 action을 일으킬 수 있도록 type과 payload(Data)를 받아 새로운 State로 설정할 수 있도록 Action들을 선언한다.
import {LOGIN, LOGOUT} from "./reducers/userReducer";
import {INIT_LIST, SET_GROUP, SET_ROOM, OPEN_GROUP, SELECT_ROOM, PUSH_MESSAGE, READ_MESSAGE, LEAVE_ROOM} from "./reducers/chatReducer";
export const login = user => ({ type: LOGIN, payload: user });
export const logout = user => ({ type: LOGOUT, payload: user });
export const initList = states => ({type: INIT_LIST, payload : states});
export const setGroup = groupData => ({type: SET_GROUP, payload: groupData});
export const setRoom = roomData => ({type: SET_ROOM, payload: roomData});
export const setConnectInfo = connectInfoData => ({type: LEAVE_ROOM, payload: connectInfoData});
export const openGroup = openStates => ({type: OPEN_GROUP, payload: openStates});
export const selectRoom = selectedStates => ({type: SELECT_ROOM, payload: selectedStates});
export const pushMessage = unreadStates => ({type: PUSH_MESSAGE, payload: unreadStates});
export const readMessage = unreadStates => ({type: READ_MESSAGE, payload: unreadStates});
상태는 반드시 Action을 통해서만 바꿀 수 있으며 그 외의 상황에서는 state를 읽는 것만 가능하다.
3. Reducer
Reducer는 Action이 일으킨 상태 변화를 Action Type에 따라 Data를 받고 이전 State와 비교하여 새로운 State를 내보낸다.
Action Type을 선언할때는 같은 타입의 액션이 있을 수 있으므로 액션 앞에 Reducer명을 붙여주거나 해서 구분한다. Reducer 내에서는 switch문으로 Action 타입에 따라 State를 비교하고 바꿔준다.
export const LOGIN = "USER/LOGIN";
export const LOGOUT = "USER/LOGOUT";
//UserReducer.js
const initialState = {
User : {
id : '',
nickname : '',
}
};
const userChecker = (state = initialState, action) => {
switch (action.type) {
case LOGIN:
return {
...state,
User : {
...state.User,
id : action.payload.id,
nickname : action.payload.nickname,
}
};
case LOGOUT:
return {
...state,
User : {
id: '',
nickname: '',
}
};
default:
return state;
}
};
export default userChecker;
Reducer를 여러개 사용하는 경우 RootReducer를 작성하여 외부에서 여러 개의 Reducer를 접근 가능하도록 한다.
import { combineReducers } from "redux";
import userReducer from "./userReducer";
import chatReducer from "./chatReducer";
const rootReducer = combineReducers({
userReducer, chatReducer
});
export default rootReducer;
4. Store
Store는 State들을 관리하는 저장소다.
createStore()함수로 store를 생성하여 외부에서 사용가능하도록 store.js를 작성한다. 이 때, redux-logger를 store에 추가하고 redux-devtools-extension을 import 하면 prevState/Action/nextState를 log로 쉽게 볼 수 있다.
import { legacy_createStore as createStore, applyMiddleware, compose } from "redux";
import rootReducer from "./reducers/rootReducer";
import logger from "redux-logger";
import { composeWithDevTools } from "redux-devtools-extension";
// logger 사용
const enhancer =
process.env.NODE_ENV === "production"
? compose(applyMiddleware())
: composeWithDevTools(applyMiddleware(logger));
const store = createStore(rootReducer, enhancer);
export default store;
createStore시 deprecated 에러가 뜬다면 아래 이전 글을 참조해보자. ㅎㅎ
2022.08.01 - [개발 Study/Node, js, react] - [Error] Redux createStore 에러 처리 (deprecated)
<Provider store={store}>
<App />
</Provider>
생성한 Store는 index.js에서 <App/> 태그 외부에 <Provider>태그를 넣고 store에 생성한 store를 넣어주면 Context를 사용할 수 있다.
자 이렇게 State/Action/Reducer/Store는 생성했다.
UseSelector/UseDispatch로 State를 가져다 쓰고, Action을 일으켜 State를 변경할 수 있다.
이를 어떻게 사용하는지 다음 글에서 알아보자.
'개발 Study > React' 카테고리의 다른 글
[React/Redux] Redux-persist 사용법 - (새로고침 후 상태 유지) (0) | 2022.08.08 |
---|---|
[React/Redux] Redux 사용법 (2) - UseDispatch/UseSelector (0) | 2022.08.05 |
[Error] Redux createStore 에러 처리 (deprecated) (0) | 2022.08.01 |
[React] UseEffect, UseRef 사용법 (0) | 2022.07.29 |
[React] Material UI를 이용한 FormDialog 구현하기 (1) | 2022.07.29 |
댓글