본문 바로가기

react

for문 대신 react map으로 게시물 리스트 구현하기 -1

for 대신 Map

실무에서는 for문 대신 map을 사용한다.
유지보수 측면에서 훨씬 이득이기 때문.

 

classMate.map((el) => (el +"어린이"))
classMate.map((el)=>el+"어린이")

화살표 함수 내 소괄호 생략 가능

 

classMate.map((el)=>({name: el.name +"어린이"}))
classMate.map((el)=>{name:el.name +"어린이"}

객체를 사용할 경우 ()=>{} 이런 형태가 되기 때문에 생략 불가능!
화살표 함수가 함수의 중괄호를 가르키는 꼴이 됨

 

 //올바른 map 예제
 
const SOUL_FOOD = [
   { number: 1, name: "돼지국밥" },
   { number: 2, name: "찜닭" },
   { number: 3, name: "물회" },
   { number: 4, name: "다리미" },
   { number: 5, name: "초밥" },
   { number: 6, name: "재철나물" },
   { number: 7, name: "서브웨이" },
];
 //mutation으로 받아온 객체 형식의 배열


export default function SoulMapPage() {

  return (
    <div>
      {SOUL_FOOD.map((el) => (<div> {el.number} {el.title} </div>))}
    </div>
  );
}



Q: 왜 컴포넌트 함수 밖에 배열을 뒀나요? 

A: 컴포넌트 함수 내에  react의 상태관리변수인  useState가 있을 경우 값이 변경될 때 마다 컴포넌트 함수 전체가 리렌더링된다.  만약 query문이나 mutation을 안에 두면 이미 DB에서 받아온 정보를 다시 한번 받아와야 하는 일이 생기기에 밖에 빼둔다. 

 

//추천하지 않는 map 예제

const SOUL_FOOD = [
   { number: 1, name: "돼지국밥" },
   { number: 2, name: "찜닭" },
   { number: 3, name: "물회" },
   { number: 4, name: "다리미" },
   { number: 5, name: "초밥" },
   { number: 6, name: "재철나물" },
   { number: 7, name: "서브웨이" },
 ];
 //mutation으로 받아온 객체 형식의 배열


const auto_circle = SOUL_FOOD.map((el) => (
     <div>
       {el.number} {el.title}{" "}
     </div>
  ));

 return <div>{auto_circle}</div>;
 

props에서 map을 가져와 사용하는 것 보다 map 자체를 return 문에 두는 편이 낫다고 한다. 

 

Map delete

문제: 

map을 이용해 화면에 띄운 정보를 삭제할 때, 

쿼리 문에서 

삭제 명령이 DB로 전송,

DB에서 성공적으로 삭제되었으나

리렌더링(페이지 새로고침)을 따로 해주지 않을 경우,

FE(화면)에 나타나지 않는다.

 

값 변경이 될 때마다 컴포넌트 함수 내 모든 정보들을  리렌더링 하는 useState와 다르다!

 

해결: 

삭제 명령어를 날리는 gql mutation 스니펫 내에서 변경될 event의 태그(타깃)의 id를 가져온다.

DB에서 변경된 값을 새로고침 없이 화면에 그려주기 위해 refetchQueries를 사용한다. 

 

refetchQuerys: 

한번에 여러 개의 쿼리를 리패치 가능하기에 뒤에 s가 붙었으며 배열 형식을 사용한다. [{}, {}, {}]

일단 하나의 쿼리만 리패치했다. 잘 작동한다. 

 

 

또 다른 문제:

체크박스에 체크 후 해당 row의 정보를 삭제할 경우 체크박스와 정보가 연동되지 않아 따로 노는 것을 발견했다. 

 

해결:

react map에게 반복문의 첫 번째 순서만 알려줘도 나머지 배열을 알아서 구현하는 능력이 있는데,  

체크박스 사용 시 단순히 맨 처음의 것만 복사해서 출력했기 때문에 생긴 문제다.

row의 요소 묶음이  한 개체, row 마다 서로 다른 개체임을 인식시켜야 한다. 

각 체크박스, 각 열마다  겹치지 않는 값으로 id를 준다. ex)  el  중에서 선택.  el.number(게시글 번호)

return (
  <div>
    {data?.fetchBoard.map((el, index) => (
      <div>
        <span> <input type="checkbox"/> </span>
        <span style={{ margin: "10px" }}>{el.number}</span>
        <span style={{ margin: "10px" }}>{el.title}</span>
        <span style={{ margin: "10px" }}>{el.writer}</span>
        <span> <button id={el.number} onClick={onClickDelete}>삭제</button> </span>
      </div>
    ))}
  </div>
);
}

index도 생성되긴 하나 받아온 10개의 정보 중  몇 번째로 실행되는지 알려주며, 

항상 고정된 자리에서 고정값을 지니기에 index를 id로 사용 시 체크박스가 각 정보마다 고유한 값을 지니질 못한다. 

index는 곧 유일하지 않다.