2 분 소요

🔮 삭제하기 버튼은 어떻게 구현?

  • hope : 삭제하기 버튼을 출력되는 일기 리스트 하나 당 제일 아래에 부분에 넣고 싶다.
  • 현재 컴포넌트 계층 구조 상태
    • App.js
      • DiarEditor.js (일기를 입력받는 곳)
      • DiaryList.js (저장 후 일기 리스트가 출력될 곳의 공간을 차지, data들을 하나씩 map함수를 이용해서 DiaryItem으로 전달)
        • DiaryItem.js (실제 저장된 일기 하나 를 출력할 수 있는 곳)

💡 How? -> step 1. 삭제 버튼 구현하기

📐 DiaryItem.js에 버튼 구현

// DiaryItem.js
const DiaryItem = ({
  onDelete,
  author,
  content,
  created_date,
  emotion,
  id,
}) => {
  return (
    <div className="DiaryItem">
      <div className="info">
        <span>
          작성자 : {author} | 감정점수 : {emotion}
        </span>
        <br />
        <span className="date"> {new Date(created_date).toLocaleString()}</span>
      </div>
      <div className="content">{content}</div>
      <button
        onClick={() => {
          console.log(id);
        }}
      >
        삭제하기
      </button>
    </div>
  );
};

export default DiaryItem;

📐 삭제 버튼 동작하기

이 버튼이 동작하기 위해서는 1️⃣ App.js 에서 onDelete 함수를 구현해서 DiaryList.js 까지 전달해주고, 2️⃣ DiaryList.js 컴포넌트를 거쳐서 3️⃣ DiaryItem.js 까지 전달이 되어야 한다.

  • 1️⃣ App.js에서 DiaryList에 onDelete 함수를 prop으로 전달

    // App.js
    const onDelete = (targetId) => {
      console.log(targetId + "가 삭제되었습니다.");
    };
    
    return (
      <div className="App">
        <DiaryEditor onCreate={onCreate} />
        <DiaryList diaryList={data} onDelete={onDelete} />
      </div>
    );
    
  • 2️⃣ 프롭을 매개변수를 통해서 전달 받고, 다시 DiaryItem으로 전달

    // DiaryList.js
    import DiaryItem from "./DiaryItem.js";
    
    const DiaryList = ({ diaryList, onDelete }) => {
      console.log(diaryList);
      return (
        <div className="DiaryList">
          <h2>일기 리스트</h2>
          <h4>{diaryList.length}개의 일기가 있습니다.</h4>
          <div>
          //dummyList의 하나의 객체가 it로 넘어옴
            {diaryList.map(
              (
                it
              ) => (
                <DiaryItem key={it.id} {...it} onDelete={onDelete} />
              )
            )}
          </div>
        </div>
      );
    };
    
    //undefined로 전달될 수 있는 값들의 기본값을 설정
    DiaryList.defaultProps = {
      diaryList: [],
    };
    
    export default DiaryList;
    
  • 3️⃣ 전달 받은 onDelete 함수를 사용

    // DiaryItem.js
    const DiaryItem = ({
      onDelete,
      author,
      content,
      created_date,
      emotion,
      id,
    }) => {
      return (
        <div className="DiaryItem">
          <div className="info">
            <span>
              작성자 : {author} | 감정점수 : {emotion}
            </span>
            <br />
            <span className="date">
              {" "}
              {new Date(created_date).toLocaleString()}
            </span>
          </div>
          <div className="content">{content}</div>
          <button
            onClick={() => {
              console.log(id);
              //window.confirm은 alert처럼 뜨지만 밑에 확인, 취소 버튼이 같이 뜬다.
              if (window.confirm(`${id}번 째 일기를 삭제하시겠습니까?`)) {
                onDelete(id); // 지울 id를 가지고 onDelete 함수 호출 -> App.js에 id값 전달
              }
            }}
          >
            삭제하기
          </button>
        </div>
      );
    };
    
    export default DiaryItem;
    

▶️ 여기까지 했다면, 무슨 일기를 삭제할 지, id를 받아옴 -> 실제 웹 페이지에서는 삭제 X. 왜? setData 함수에서 랜더링하는 리스트에 삭제되어야 할 id가 전달되지 않았으므로 data에 전달되는 값은 삭제해야되는 data까지 그대로 전달이 된다.

💡 How? -> step 2. 삭제될 아이템 빼고 랜더링하기

이미 DiaryItem.js에서 지울 id값을 가지고 App.js에 있는 함수를 호출했다. 그러면 여기서 그 지울 id를 제외한 나머지 id를 가지고 newDiaryList 를 만들고 newDiaryList를 setData로 전달하여 새로운 데이터를 다시 랜더링 한다.

  • filter 함수 : 주어진 함수의 테스트(함수 구현부)를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.
// App.js
const onDelete = (targetId) => {
  const newDiaryList = data.filter((it) => it.id !== targetId);
  setData(newDiaryList);
};

이 함수에서는 it의 id값이 targetId와 다른 id값들만 newDiaryList로 반환되는 것을 확인할 수 있습니다.

🌗 결과

download1

삭제하기 버튼 클릭 ⬇️

download2

삭제하기 완료 ⬇️

download3

태그:

카테고리:

업데이트:

댓글남기기