컴포넌트에서 상태변화 로직을 분리하자.
첫번째 count 기존의 사용했던 state
두번째 dispatch 상태를 변화시키는 action
reducer dispatch 상태변화함수를 처리하는 로직
1 count state의 초기값이다.
기존에 작성했던 useState는 주석처리를 해주고
useReducer를 작성해보자.
App.js
//const [data, setData] = useState([]);
useState대신 useReducer를 쓰는 이유는. 복잡한 상태변화를 로직을 컴포넌트 밖으로 분리하기 위해서다.
import { useCallback, useReducer, useState, useRef, useEffect, useMemo } from 'react';
const [data, dispatch] = useReducer(reducer, []);
const reducer = (state, action) => {
switch(action.type){
case 'INIT' :
case 'CREATE' :
case 'REMOVE' :
case 'EDIT':
default :
return state;
}
}
INIT -> getData
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);
}
const reducer = (state, action) => {
switch(action.type){
case 'INIT' : {
return action.data
}
}
}
CREATE -> onCreate
const onCreate = useCallback((author, content, emotion) => {
dispatch({type:'CREATE', data:{author, content, emotion, id:dataId.current}});
dataId.current += 1;
//const created_date = new Date().getTime();
// const newItem = {
// author,
// content,
// emotion,
// created_date,
// id : dataId.current
// }
//setData((data)=>[newItem, ...data]);
},[]);
case 'CREATE' :{
const created_date = new Date().getTime();
const newItem = {
...action.data,
created_date
}
return [newItem, ...state];
}
REMOVE -> onRemove
const onRemove = useCallback((targetId) =>{
dispatch({type:'REMOVE', targetId});
//setData(data=>data.filter((it)=>it.id!==targetId));
},[]);
case 'REMOVE' : {
return state.filter((it)=>it.id!== action.targetId);
}
onEdit -> EDIT
const onEdit = useCallback((targetId, newContent) => {
dispatch({type:'EDIT', targetId, newContent})
// setData((data)=>
// data.map((it)=>
// it.id === targetId ? {...it, content:newContent} : it
// )
// )
},[])
case 'EDIT': {
return state.map((it)=>it.id === action.targetId ? {...it, content:action.newContent} : it)
}