상태관리 세팅하기
프로젝트 전반적으로 사용될 일기 데이터 State 관리 로직 작성하기
프로젝트 State Context 세팅하기
일기 데이터 State를 공급할 Context를 생성하고 Provider로 공급하기
프로젝트 Dispatch Context 세팅하기
일기 데이터 State의 Dispatch 함수들을 공급할 Context를 생성하고 Provider로 공급하기
현재 만드는 프로젝트의 컴포넌트 구성입니다. 먼저 App 컴포넌트에 일기 데이터 State를 만들고
관리할 수 있는 기능을 만들어 보도록 하겠습니다.
App.js
import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Edit from "./pages/Edit";
import New from "./pages/New";
import Diary from "./pages/Diary";
function App() {
return (
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/new" element={<New />}></Route>
<Route path="/edit" element={<Edit />}></Route>
<Route path="/diary/:id" element={<Diary />}></Route>
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
전 게시글에도 정리가 되어있지만 다시 리마인드 해보면서 useReducer를 사용하여 일기 데이터 State 관리 로직을 작성해보겠습니다.
const [data, dispatch] = useReducer(reducer, []);
컴포넌트 바깥에 reducer 함수를 선언해 줍니다.
const reducer = (state, action) => {
let newState = [];
switch (action.type) {
case "INIT": {
return action.data;
}
case "CREATE": {
newState = [action.data, ...state];
break;
}
case "EDIT": {
state.map((it) => (it.id === action.data.id ? { ...action.data } : it));
break;
}
case "REMOVE": {
newState = state.filter((it) => it.id !== action.targetId);
break;
}
default:
return state;
}
return newState;
};
reducer 함수는 첫반째 인자로 현재 state의 상태, 두번째 인자로 type과 기타 행동에 필요한 데이터들이 넘어옵니다.
이제 컴포넌트 안에서 해당 dispatch를 호출해보도록 하겠습니다.
function App() {
const [data, dispatch] = useReducer(reducer, []);
const dataId = useRef(0);
const onCreate = (date, content, emotion) => {
dispatch({
type: "CREATE",
data: {
id: dataId.current,
date: new Date(date).getTime(),
content,
emotion,
},
});
};
const onRemove = (targetId) => {
dispatch({
type: "REMOVE",
targetId,
});
};
const onEdit = (targetId, date, content, emotion) => {
dispatch({
type: "EDIT",
data: {
id: targetId,
date: new Date(date).getTime,
content,
emotion,
},
});
};
이제 react context를 사용하여 하위 컴포넌트 어디서든 사용 가능하게 하도록 하겠습니다.
app 컴포넌트 바깥에 선언하도록 합니다.
export const DiaryStateContext = React.createContext();
export const DiaryDispatchContext = React.createContext();
//... 생략
return (
<DiaryStateContext value={data}>
<DiaryDispatchContext value={(onCreate, onEdit, onRemove)}>
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/new" element={<New />}></Route>
<Route path="/edit" element={<Edit />}></Route>
<Route path="/diary/:id" element={<Diary />}></Route>
</Routes>
</div>
</BrowserRouter>
</DiaryDispatchContext>
</DiaryStateContext>
);
선언을 해주고 value에 data와 onCreate 등의 함수를 전달하였습니다. 최적화는 일단 신경쓰지 않도록 하겠습니다.
import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Edit from "./pages/Edit";
import New from "./pages/New";
import Diary from "./pages/Diary";
import React, { useReducer, useRef } from "react";
const reducer = (state, action) => {
let newState = [];
switch (action.type) {
case "INIT": {
return action.data;
}
case "CREATE": {
newState = [action.data, ...state];
break;
}
case "REMOVE": {
newState = state.filter((it) => it.id !== action.targetId);
break;
}
case "EDIT": {
newState = state.map((it) =>
it.id === action.data.id ? { ...action.data } : it
);
break;
}
default: {
return state;
}
}
return newState;
};
export const DiaryStateContext = React.createContext();
export const DiaryDispatchContext = React.createContext();
function App() {
const [data, dispatch] = useReducer(reducer, []);
const dataId = useRef(0);
const onCreate = (date, content, emotion) => {
dispatch({
type: "CREATE",
data: {
id: dataId.current,
date: new Date(date).getTime(),
content,
emotion,
},
});
};
const onRemove = (targetId) => {
dispatch({
type: "REMOVE",
targetId,
});
};
const onEdit = (targetId, date, content, emotion) => {
dispatch({
type: "EDIT",
data: {
id: targetId,
date: new Date(date).getTime,
content,
emotion,
},
});
};
return (
<DiaryStateContext value={data}>
<DiaryDispatchContext value={(onCreate, onEdit, onRemove)}>
<BrowserRouter>
<div className="App">
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/new" element={<New />}></Route>
<Route path="/edit" element={<Edit />}></Route>
<Route path="/diary/:id" element={<Diary />}></Route>
</Routes>
</div>
</BrowserRouter>
</DiaryDispatchContext>
</DiaryStateContext>
);
}
export default App;
리액트 공식 홈페이지
https://ko.legacy.reactjs.org/docs/react-api.html#reactmemo
해당 게시글은 인프런 강의
"한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지(이정환)"
를 정리한 내용입니다. 쉽게 잘 설명해주시니 여러분도 강의를 듣는 것을 추천드립니다.
redux 패턴 참조
https://www.daleseo.com/react-hooks-use-reducer/