→ props 드릴링 방식을 이용해서 비효율적임

→ props 드릴링 X

Context 생성
const MyContext = React.createContext(defaultValue);
Context Provider를 통한 데이터 공급
<MyContext.Provider value={전역으로 전달하고자하는 값}>
{/*이 Context안에 위치할 자식 컴포넌트들*/}
</MyContext.Provider>
App.js
import React, {
useCallback,
useMemo,
useEffect,
useRef,
useReducer,
} from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
import LifeCycle from "./Lifecycle";
// import OptimizeTest from "./OptimizeTest";
const reducer = (state, action) => {
switch (action.type) {
case "INIT": {
return action.data; // 이게 새로운 state가 된다.
}
case "CREATE": {
const created_date = new Date().getTime();
const newItem = {
...action.data,
created_date,
};
return [newItem, ...state];
}
case "REMOVE": {
return state.filter((it) => it.id !== action.targetId);
}
case "EDIT": {
return state.map((it) =>
it.id === action.targetId ? { ...it, content: action.newContent } : it
);
}
default:
return state;
}
};
export const DiaryStateContext = React.createContext();
export const DiaryDispatchContext = React.createContext();
function App() {
// const [data, setData] = useState([]);
const [data, dispatch] = useReducer(reducer, []);
const dataId = useRef(0);
const getData = async () => {
const res = await fetch(
"<https://jsonplaceholder.typicode.com/comments>"
).then((res) => res.json());
const initData = res.slice(0, 20).map((it) => {
return {
author: it.email,
content: it.body,
emotion: Math.floor(Math.random() * 5) + 1,
created_date: new Date().getTime(),
id: dataId.current++,
};
});
dispatch({ type: "INIT", data: initData });
// setData(initData);
};
useEffect(() => {
getData();
}, []);
const onCreate = useCallback((author, content, emotion) => {
dispatch({
type: "CREATE",
data: {
author,
content,
emotion,
id: dataId.current,
},
});
dataId.current += 1;
}, []);
const onDelete = useCallback((targetId) => {
dispatch({ type: "REMOVE", targetId });
}, []);
const onEdit = useCallback((targetId, newContent) => {
dispatch({ type: "EDIT", targetId, newContent });
}, []);
// useMemo 활용하는 이유는 App 컴포넌트가 재생성될떄 해당 dispatches도 재생성되기 때문에
// useMemo로 묶어서 최적화 풀리지않게 보내야함
const memoizedDispatches = useMemo(() => {
return { onCreate, onDelete, onEdit };
}, []);
const getDiaryAnalysis = useMemo(() => {
const goodCount = data.filter((it) => it.emotion >= 3).length;
const badCount = data.length - goodCount;
const goodRatio = (goodCount / data.length) * 100;
return { goodCount, badCount, goodRatio };
}, [data.length]);
const { goodCount, badCount, goodRatio } = getDiaryAnalysis;
return (
<DiaryStateContext.Provider value={data}>
<DiaryDispatchContext.Provider value={memoizedDispatches}>
<div className="App">
<DiaryEditor />
<div>전체 일기 : {data.length}</div>
<div>기분 좋은 일기 개수 : {goodCount}</div>
<div>기분 나쁜 일기 개수 : {badCount}</div>
<div>기분 좋은 일기 비율 : {goodRatio}</div>
<DiaryList />
</div>
</DiaryDispatchContext.Provider>
</DiaryStateContext.Provider>
);
}
export default App;
DiaryList.js