오늘의 트러블 슈팅
데이터를 받아오는 과정이 잘못되었다.
Map 함수 오류......
원래 코드
//AdItem.tsx
const AdCard = (dailyAd: AdListDataType) => {
return (
<ul data-id={dailyAd.id}>
<li>id: {dailyAd.id}</li>
<li>adType: {dailyAd.adType}</li>
<li>title: {dailyAd.title}</li>
<li>budget: {dailyAd.budget}</li>
<li>status: {dailyAd.status}</li>
<li>startDate: {dailyAd.startDate}</li>
<li>endDate: {dailyAd.endDate}</li>
<li>cost: {dailyAd.report.cost}</li>
<li>convValue: {dailyAd.report.convValue}</li>
<li>roas: {dailyAd.report.roas}</li>
</ul>
);
};
export default function AdItem() {
const [adList, setAdList] = useRecoilState(adListState);
React.useEffect(() => {
// getAdList();
adListRequest.get("").then((response) => {
setAdList(response.data);
});
}, []);
const dailyAdList: JSX.Element[] = (adList === null ? [] : adList)?.map(
(dailyAd: AdListDataType) => <AdCard {...dailyAd} key={dailyAd.id} />
);
return (
{dailyAdList}
);
}
//atom.ts
export const adListSelector = selector({
key: "adListSelector",
get: async ({ get }) => {
const response: AxiosResponse<any, any> = await adListRequest.get("");
return response.data;
},
});
export const adListState = atom({
key: "adListState",
default: [],
});
해결 코드
//AdItem.tsx
import React from "react";
import { useRecoilState } from "recoil";
import { adListRequest } from "../axiosFactory/adListAxios";
import { AdListDataType } from "../models/types";
import { adListState } from "../store/atom";
export default function AdItem() {
const [adList, setAdList] = useRecoilState<AdListDataType[]>(adListState);
React.useEffect(() => {
adListRequest.get("").then((response) => {
setAdList(response.data);
});
}, []);
console.log(adList[0].adType);
return (
<div>
{adList?.map((dailyAd: AdListDataType) => (
<ul key={dailyAd.id}>
<li>id: {dailyAd.id}</li>
<li>adType: {dailyAd.adType}</li>
<li>title: {dailyAd.title}</li>
</ul>
))}
</div>
);
}
//atom.ts
export const adListSelector = selector({
key: "adListSelector",
get: async ({ get }) => {
const response: AxiosResponse<any, any> = await adListRequest.get("");
return response.data;
},
});
export const adListState = atom({
key: "adListState",
default: adListSelector,
});
리코일의 atom의 default 값을 selector를 가리키게 했더니, 해결이되었다. 왜 그러지?? state같은경우 기본값을 설정하고 selector로 바꿔준다고 생각을 했는데.... 이부분은 리코일을 더 공부해봐야겠다.
그리고, 간단하게 보이려 처음에는 AdCard 컴포넌트를 분리했는데, 이부분이 더 혼란스러워서 코드를 정리했다!
문제
const [adList, setAdList] = useRecoilState(adListState);
해결
const [adList, setAdList] = useRecoilState<AdListDataType[]>(adListState);
이렇게 안받아와졌다!
<li>id: {dailyAd.id}</li>
왜 ??
찾아보자!
지금까지의 레이아웃은 이렇다.
이제 기본적인 마크업을 카드형식으로 해주고, 카드형식으로 담아서 불러오는것을 해주려한다.
이후, CRUD를 순차적으로 진행해보려한다.
광고만들기 버튼 클릭시 : OnClick 이벤트로 모달형식으로 ? 띄워보자
C : input들을 다 입력하면 put 으로 server 연동
R : database에 있는 값들을 화면에 보여주기 지금처럼!
U : 수정 버튼을 클릭하였을 시 input으로 값을 변경할 수 있도록 해주고 저장하기 하면 put
D : 삭제 버튼 클릭 시 delete!!
기본적인 마크업 완료
쉬운것부터 처리해보자!
D부터!
const handleDeleteClick = (
params: number,
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
console.log("삭제클릭");
console.log(params);
deleteAdList(params);
};
<Button
size="small"
variant="outlined"
color="warning"
onClick={(e) => {
handleDeleteClick(dailyAd.id, e);
}}
>
삭제하기
</Button>
문제사항 발생!
이런식으로 AdItem 컴포넌트에 adList를 가져와서 map을 돌리면서 카드를 만들어내는데, 그 카드마다 삭제 버튼도 생성되고 -> 그럼그걸 click이벤트 넣어서 deleteAdlist()하려 함 -> 그러려면 그 map돌린것의 adList의 .id 값이 들어가야할거같은데 -> id를 어떻게 받아올까?
버튼마다 onclick이벤트가 달리고, 메소드가 연결될텐데, 그 시점에는 해당 카드에 연결된 데이터의 id를 알 수 있으니까 그 때 파라미터로 전달해 줄 수도 있지 않을까?? ->
<Button ~~ onClick={handleDeleteClick}></Button>
이렇게 안된다.
왜 ??
리액트에서 함수 연결 할 때는 호출을 하면 안되고 함수 선언을 넘겨야 한다!!
리액트 함수 파라미터 전달 구글링 -> 화살표 함수를 이용하여 원래 부르려던 함수를 감싸고, 해당 함수의 호출부에서 인자를 넘겨주기
const handleDeleteClick = (
params: number | null,
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
console.log("삭제클릭");
console.log(params);
deleteAdList(params);
};
<Button onClick={(e) => {handleDeleteClick(dailyAd.id, e);}} </Button>
console에는 아주 잘찍힌다!
params로 넣어준 type문제였다!
해결!
일단, 라우팅 부분에서 문제가있는건지, AdItem의 map부분의 문제가 있는건지, 라우팅 될 때 에러가 뜨고, 새로고침하면 괜찮아진다. 이부분은 내일 고쳐봐야겠다.
또한, 세개의 기능의 get이 type에 따라 다르게 정의되었는데, 이부분을 리팩토링할 방법을 고민해보아야겠다.
get_total(url: string) {
return this.service.get<TotalAdStatusType[]>(url);
}
get_channel(url: string) {
return this.service.get<ChannelStatusType[]>(url);
}
get_ad(url: string) {
return this.service.get(url);
}
기능을 다 끝내고 난 다음, 헤더와 메뉴바를 제외하고 나머지 영역만 스크롤이 가능하도록 만드는것에 대해 내일 고민해봐야겠다.