해결된 질문
작성
·
28
·
수정됨
0
해당 챕터에서 강의대로 진행했고 몇번을 다시 확인해봐도
차이점을 도통 찾지 못해서 문의드립니다.
Home.jsx에서 데이터를 필터걸어도 걸리지않는 상황
DiaryList.jsx에서 DiaryItem으로 데이터를 보내도 받는쪽에서 받지 못하는 상황(개발자도구에서는 워닝으로
hook.js:608 Warning: Each child in a list should have a unique "key" prop) 발생
이하 소스첨부 드립니다.
App.jsx
import './App.css'
import { useReducer, useRef, createContext } from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import Diary from './pages/Diary';
import New from './pages/new';
import Edit from './pages/Edit';
import Notfound from './pages/Notfound';
const mockData =[
{
id : 1,
createdDate : new Date("2024-12-6").getTime(),
emotionId : 1,
content : "1번 일기내용",
},
{
id : 2,
createdDate : new Date("2024-12-5").getTime(),
emotionId : 2,
content : "2번 일기내용",
},
{
id : 3,
createdDate : new Date("2024-11-15").getTime(),
emotionId : 3,
content : "3번 일기내용",
},
]
function reducer(state, action){
switch(action.type){
case 'CREATE' :
return [action.data, ...state]
case 'UPDATE' :
return state.map((item)=>
String(item.id) === String(action.data.id) ? action.data : item)
case 'DELETE' :
return state.filter((item) => String(item.id) !== String(action.id));
default :
return state;
}
}
export const DiaryStateContext = createContext();
export const DiaryDispatchContext = createContext();
function App() {
const [data, dispatch] = useReducer(reducer, [mockData]);
const idRef = useRef(3);
const onCreate =(createdDate, emotionId, content) => {
dispatch({
type:"CREATE",
data : {
id : idRef.current++,
createdDate,
emotionId,
content,
},
})
}
const onUpdate = (id,createdDate , emotionId, content) => {
dispatch(
{
type : "UPDATE",
data : {
id,
createdDate,
emotionId,
content,
},
}
)
}
const onDelete = (id) => {
dispatch(
{
type : "DELTE",
data : {
id,
}
}
)
}
return (
<>
<DiaryStateContext.Provider value={data}>
<DiaryDispatchContext.Provider
value={{
onCreate,
onUpdate,
onDelete,
}}
>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/new" element={<New />}></Route>
<Route path="/diary/:id" element={<Diary />}></Route>
<Route path="/edit/:id" element={<Edit />}></Route>
<Route path="*" element={<Notfound />}></Route>
</Routes>
</DiaryDispatchContext.Provider>
</DiaryStateContext.Provider>
</>
);
};
export default App
Home.jsx
import { useState, useContext } from "react";
import { DiaryStateContext } from "../App";
import Button from "../components/button";
import Header from "../components/Header"
import DiaryList from "../components/DiaryList";
const getMonthlyData = (pivotDate, data) =>{
const beginTime = new Date(
pivotDate.getFullYear(),
pivotDate.getMonth(),
1,
0,
0,
0
).getTime();
const endTime = new Date(
pivotDate.getFullYear(),
pivotDate.getMonth() + 1,
0,
23,
59,
59
).getTime();
console.log('필터시작일자 : ' + beginTime + '필터종료일자' + endTime)
return data.filter((item)=> beginTime <= item.createdDate <= endTime);
}
const Home = () => {
const data = useContext(DiaryStateContext);
const [pivotDate,setPivotDate] = useState(new Date());
const monthlyData = getMonthlyData(pivotDate, data);
console.log(monthlyData);
const onIncreaseMonth = () => {
setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() + 1)
);
};
const onDecreaseMonth = () => {
setPivotDate(new Date(pivotDate.getFullYear(), pivotDate.getMonth() - 1)
);
};
return <div>
<Header title = {`${pivotDate.getFullYear()} 년 ${
pivotDate.getMonth()+ 1 }월`}
leftChild={<Button onClick={onDecreaseMonth} text="<" />}
rightChild={<Button onClick={onIncreaseMonth} text=">" />}
/>
<DiaryList data={monthlyData} />
</div>;
}
export default Home;
DiaryList.jsx
import './DiaryList.css'
import Button from "./button";
import DiaryItem from './DiaryItem';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
const DiaryList = ({data}) => {
const nav = useNavigate();
const [sortType, setSortType] = useState("latest");
const onChangeSortType = (e) => {
setSortType(e.target.value);
};
const getSortedDate = () => {
return data.toSorted((a, b) => {
if(sortType ==='oldest'){
return Number(a.createdDate) - Number(b.createdDate);
} else {
return Number(b.createdDate) - Number(a.createdDate);
}
});
}
const sortedData = getSortedDate();
return (
<div className="DiaryList">
<div className="menu_bar">
<select>
<option value={"latest"}>최신순</option>
<option value={"oldest"}>오래된순</option>
</select>
<Button
onClick = {() => nav("/new")}
text={"새 일기 쓰기"}
type={"POSITIVE"} />
</div>
<div className="list_wrapper">
{sortedData.map((item)=><DiaryItem key={item.id} {...item}/>)}
</div>
</div>
);
};
export default DiaryList;
DiaryItem.jsx
import getEmotionImage from "../util/get-emotion-image"
import Button from "./button";
import "./DiaryItem.css";
import { useNavigate } from "react-router-dom";
const DiaryItem = ({id, emotionId, createdDate, content}) => {
const nav = useNavigate();
return (
<div className="DiaryItem">
<div
onClick={()=>nav(`/diary/${id}`)}
className={`img_section img_section_${emotionId}`}
>
<img src={getEmotionImage(1)} />
</div>
<div
onClick={()=>nav(`/diary/${id}`)}
className="info_section">
<div className="created_date">
{new Date(createdDate).toLocaleDateString()}
</div>
<div className="content">{content}</div>
</div>
<div className="button_section">
<Button
onClick={()=>nav(`/edit/${id}`)}
text={"수정하기"} />
</div>
</div>
)
};
export default DiaryItem;
답변 1
0
안녕하세요 이정환입니다.
보내주신 코드로만 봤을 때에는 Home.jsx에 오류의 getMonthlyData 함수에 오류가 있네요
아래 그림에서 드래그 한 부분 보시면 됩니다.
확인해보시면 비교문이 이상하게 작성되어 있습니다.
beginTime <= item.createdDate <= endTime 이 아닌
beginTime <= item.createDate && item.createdDate < endTime 으로 수정하셔야 합니다.
안녕하세요!
필터가 안걸리고 데이터가 안보이는게 가장 큰 문제여서 이것저것 수정하다보니 잘못된 코드까지 들어갔었내여
다시한번 꼼꼼히 보니
App.jsx에
const [data, dispatch] = useReducer(reducer, [mockData]);
mockData에 괄호가 들어가서 생긴문제였습니다
바쁘신대 확인 감사합니다