처음에는 리덕스의 개념을 이해하는 것이 쉽지 않았다. 하지만 코드를 보며 몇 번 적용해보니 기본적인 개념이 이해가 되었다.
내가 생각하는 리덕스란
보통 데이터를 주고받을 때, 부모 - 자식 컴포넌트로 데이터를 전달하지만, 이곳저곳에서 다양하게 공통으로 쓰이는 글로벌 데이터라면,
자식-부모-조부모-삼촌-조카 이런식으로 여러 컴포넌트로 복잡하게 전달해줘야 할 것이다.
글로벌 저장소에 데이터를 저장해놓고 필요할때 어디서든 간단하게 소환할 수 있도록 하는 라이브러리가 리덕스(Redux) 라고 생각한다.
Redux-persist 란
리덕스를 사용해서 글로벌 저장소에 들어간 데이터는 아쉽게도 새로고침 한방이면 초기화되며 수명을 다한다.
이때 Web Storage에 저장해줘야 하는데 저장과 삭제를 쉽게 해주는 라이브러리가 Redux-persist 이다.
- localStorage에 저장하고 싶으면 → import storage from 'redux-persist/lib/storage
- session Storage에 저장하고 싶으면 → import storageSession from 'redux-persist/lib/storage/session
리덕스 기본 개념에 대해서 햇갈리신다면 개념익히고 오기 ↓↓↓
React(57) Redux 로 객체 저장하기 (redux 상태관리)
자 이제 Redux 로 Redux-persist 를 사용하여 저장해보자
model/Reply.ts
먼저 인터페이스에 타입을 선언해주자
export interface Reply { // 댓글의 객체 타입을 선언
id?: number;
reply: string;
createdAt?: string;
updatedAt?: string;
deletedAt?: string;
}
redux/Reply.ts
여기서 타입과 액션 그리고 리듀서를 선언한다. (얘네들을 얽히섥히 관계가 나름있는데 ...)
타입을 선언하면, → 타입을 액션에 넣고, → 리듀서에서 액션 타입에 따라 뭘 실행할 지 결정한다.
import { Reply } from 'model/Reply'; // 위에서 선언한 타입을 가져와서 사용하자
// 타입 선언
type replyAction = ReturnType<typeof initReply> | ReturnType<typeof setReply>;
const INITREPLY = 'reply/INITREPLY' as const;
const SETREPLY = 'reply/SETREPLY' as const;
const initialState: Reply[] = []; // 댓글 리스트를 받기위해 타입과 초기값으로 배열[]선언
// 액션들
export const initReply = (): { type: string; payload?: null } => ({
type: INITREPLY // 초기화 해주는 액션이므로 타입만 존재하고 페이로드는 없다
});
export const setReply = (replies: Reply[]): { type: string; payload: Reply[] } => ({
type: SETREPLY, // 타입이 분기점 역할을 해서 아래 리듀서에서 분기한다
payload: replies, // 페이로드에는 객체배열을 담은 댓글 리스트 객체가 들어간다
});
// 리듀서 (↓ 초기값과, 액션을 인자로 넣어주고)
function Reply(preState: Reply[] = initialState, action: replyAction): Reply[] {
switch (action.type) { // 액션의 타입에 따라 다른 케이스가 실행된다!
case INITREPLY: // 타입이 [이닛리플] 이면
return []; // → 빈 배열 값이 리턴되고
case SETREPLY: // 타입이 [셋리플] 이면
return <Reply[]>action.payload; // → 액션이 가진 값(페이로드)이 리턴된다
default: // 디폴트는 (빼놓으면 섭하지)
return preState; // → 초기화된 값으로 리턴!
}
}
export default reply;
redux/index.ts
여기서는 여러 리듀서들을 모아모아~ 루트리듀서를 만든다.
이제 어디서든 루트 리듀서를 소환하기만 하면 당신은 글로벌 데이터를 사용할 수가 있는 것이다.
import { CombinedState, combineReducers } from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import { PersistPartial } from 'redux-persist/es/persistReducer';
import storage from 'redux-persist/lib/storage';
import hardSet from 'redux-persist/lib/stateReconciler/hardSet';
import reply from 'redux/Reply'; // 여기서 가져오기
const rootPersistConfig = { // 루트 config 설정
key: 'root',
storage,
whitelist: ['user', 'payment', 'reply'],
stateReconciler: hardSet,
};
const replyPersistConfig = { // 댓글 config 설정
key: 'reply',
storage,
stateReconciler: hardSet,
};
... 생략 ...
const rootReducer = combineReducers({ // 루트리듀서 선언 (컴바인리듀서 안에 각각의 리듀서들 넣어 합쳐주기)
reply: persistReducer(replyPersistConfig, reply), // 이런식으로 persistReducer에 넣어준다.
user: persistReducer(userPersistConfig, user),
payment: persistReducer(paymentPersistConfig, payment),
});
export type rootState = ReturnType<typeof rootReducer>;
export default persistReducer<any, any>(rootPersistConfig, rootReducer);
ReplyComponent.tsx
실제로 쓰이는 컴포넌트에서 데이터를 글로벌화 시키기 위해 dispatch 를 통해 redux 에 저장시켜준다.
import { ReactElement, useState } from 'react';
import { useDispatch } from 'react-redux'; // 필요한 redux 애들 임포트
import { setReply } from 'redux/Reply'; // redux에서 만들었던 set함수 임포트
const ReplyComponent = (): ReactElement => {
const replyList: Reply[] = [{ // 댓글 리스트
id: 1,
reply: '첫번째 댓글 감사합니다.',
createdAt: '2022-01-11',
updatedAt: '2022-01-15',
deletedAt: '2022-01-17'
},{
id: 2,
reply: '두번째 댓글 감사합니다.',
createdAt: '2022-01-11',
updatedAt: '2022-01-20',
deletedAt: '2022-01-25'
}]
const dispatch = useDispatch(); // 디스패치를 준비해주자
dispatch(setReply(list)); // 그 [list]를 디스패치로 리덕스 속에 저어장
... 생략 ...
}
export default ReplyComponent
결과화면
크롬 리덕스 툴로 확인하니 아주 잘 저장되었다!
'React' 카테고리의 다른 글
React(59) 맵(Map) 사용하기 - set / get / has / delete / clear / size (0) | 2022.02.04 |
---|---|
React(58) - 화살표 회전 애니메이션 만들기 (0) | 2022.02.03 |
React(56) a 태그에서 onClick 이벤트 사용하기 (무효화) (2) | 2022.01.30 |
Styled-components(4) 배열로 된 div를 2열로 나열하기 (0) | 2022.01.17 |
Styled-components(3) 자식 컴포넌트에 커스텀 css props로 전달하기 (0) | 2022.01.07 |
댓글