과제의 마지막 단계 리덕스..
context 했던 2가지, 모든 레터를 관리하는 letters와 선택한 멤버를 관리하는 selectMember를 리덕스로 하기로 했다.
금요일 밤, 진영튜터님께 질문하러 갔었다.
뭔지 대충 알거같기는 한데.. 어려워서 도움을 요청했었는데,
같이 진행하다가, 과제와 다르게 리덕스 개념을 아는게 중요하다고 하셨다. 일과시간 21시가 끝난뒤 21시 45분에 나 때문에 특강이 열렸다.
1시간을 개념, 1시간조금넘어서 어떤식으로 활용하는지 알려주셨고
개념은 확실히 알게 되었다.
☞ Ruducer의 쉬운 예시 : State를 작업지시서의 내용에 따라 변경하는 공장)
☞ Action의 쉬운 예시 : 리듀서 공장에 보내는 작업지시서
☞ Action Creator의 쉬운 예시 : 공장에 보낼 작업지시서를 만드는 사람
☞ Dispatch의 쉬운 예시 : 작업지시서를 공장에 보내는 행위
// configStore.js
import { combineReducers, createStore } from "redux";
import letterReducer from "redux/reducers/letterReducer";
import selectMemberReducer from "redux/reducers/selectMemberReducer";
const rootReducer = combineReducers({
letter: letterReducer,
selectMember: selectMemberReducer,
});
const store = createStore(rootReducer);
export default store;
☞ 위에처럼 설정하기
//Router.js
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "pages/Home";
import Detail from "pages/Detail";
import { Provider } from "react-redux"; // 추가된 부분
import store from "redux/config/configStore";
const Router = () => {
return (
<BrowserRouter>
<Provider store={store}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/detail/:id" element={<Detail />} />
</Routes>
</Provider>
</BrowserRouter>
);
};
export default Router;
☞ 로 감싸주기
//letterReducer.js
import data from "../../shared/data.json";
import uuid from "react-uuid";
// 액션 타입 정의
const ADD_LETTER = "letter/ADD_LETTER";
const UPDATE_LETTERS = "letter/UPDATE_LETTERS";
// 액션 생성자 함수
export const addLetter = (newLetter) => ({
type: ADD_LETTER,
payload: {
...newLetter,
id: uuid(),
},
});
export const updateLetters = (updatedLetters) => ({
type: UPDATE_LETTERS,
payload: updatedLetters,
});
// 초기 상태
const initialState = {
letters: data.map((aData) => ({
...aData,
id: uuid(),
})),
};
// 리듀서
const letterReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_LETTER:
return {
letters: [...state.letters, action.payload],
};
case UPDATE_LETTERS:
return {
letters: action.payload,
};
default:
return state;
// return {
// letters: [~~, ~~~, ~~~]
// }
}
};
export default letterReducer;
//selectMemberReducer.js
// 액션 타입 정의
const UPDATE_SELECTED_MEMBER = "selectMember/UPDATE_SELECTED_MEMBER";
// 액션 생성자
export const updateSelectedMember = (selectedMember) => ({
type: UPDATE_SELECTED_MEMBER,
payload: selectedMember,
});
// 초기 상태
const initialState = {
selectedMember: "전체보기",
};
// 리듀서
const selectMemberReducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_SELECTED_MEMBER:
return {
selectedMember: action.payload,
};
default:
return state;
// {
// selectedMember: "전체보기",
// };
}
};
export default selectMemberReducer;
LetterReducer
1) 'ADD_LETTER'와 'UPDATE_LETTERS'라는 두 가지 액션 타입을 정의함
2) 'addLetter' 함수는 새로운 편지를 추가하며, 해당 편지에는 고유한 UUID가 부여됨
3) 'updateLetters' 함수는 여러 편지를 한 번에 업데이트함
4) 초기 상태는 'data.json' 파일에서 가져온 데이터를 기반으로 하며, 각 편지에는 UUID가 할당됨
5) 리듀서는 주어진 액션에 따라 상태를 업데이트하고, 기본적으로는 현재 상태를 그대로 반환함
selectMemberReducer
1) 'UPDATE_SELECTED_MEMBER'라는 액션 타입을 정의함
2) 초기 상태는 'selectedMember' 속성이 "전체보기"로 설정되어있음
3) 리듀서는 'UPDATE_SELECTED_MEMBER' 액션에 대한 처리를 하고, 선택된 회원 정보를 주어진 액션의 payload
로 업데이트함
4) 기본적으로는 현재 상태를 그대로 반환하여 다른 액션에는 반응하지 않음
1) useContext 대신에 useSelector를 사용하여 Redux 스토어의 상태 가져오기
const letters = useSelector((state) => state.letter.letters);
☞ useSelector를 사용하여 Redux 스토어에서 letter 리듀서의 letters 상태를 이렇게 불러 올수 있음.
2) useContext 대신에 useDispatch를 사용하여 액션을 디스패치 하기
const deleteBtn = () => {
const alertDelete = window.confirm("정말 삭제할래요?");
if (alertDelete) {
const updatedLetters = letters.filter((item) => item.id !== foundData.id);
navigate("/");
dispatch(updateLetters(updatedLetters));
}
};
☞ 이런식으로 디스패치를 하면 삭제나, 수정 등 변경이 가능함
둘의 차이는 스토어의 상태를 읽고 업데이트하는 데, 그러니까 단순하게 불러오는거는 useSelector를 사용하고 뭔가 수정을 하던 뭔가 작업이 필요하면 useDispatch를 이용해서 변경 작업을 함
프로젝트명 : 쿠로미 & 마이멜로디 아티스트 팬레터함
기간 : 2023. 11. 10 ~ 11. 20 (10일)
프로젝트 설명 : 아티스트에게 팬레터를 작성 할 수 있는 사이트
사용한 기술 : react, redux, uuid, styled-components
화면 구성 :
[Home 화면]
[Detail 화면]