전화번호부의 특정 아이템을 삭제하는 함수를 만들어봅시다.


이번 장에서는 전화번호부 아이템을 삭제하는 handleRemove 함수를 만들어보겠습니다. 먼저 App 컴포넌트를 아래와 같이 수정해주세요.

import React, { Component } from "react";
import InputBox from "./components/InputBox";
import PhoneList from "./components/PhoneList";
import "./App.css";
import { dummyData, nextId, setNextId } from "./lib/dummyData.js";

class App extends Component {
  state = {
    dummyData,
    name: "",
    phone: ""
  };

  handleInput = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  handleSubmit = () => {
    const { dummyData, name, phone } = this.state;

    if (name === "" || phone === "") return;

    this.setState({
      dummyData: {
        ...dummyData,
        [nextId]: {
          id: String(nextId),
          name,
          phone
        }
      },
      name: "",
      phone: ""
    });

    setNextId();
  };

  handleRemove = id => {
    const { [id]: _, ...dummyData } = this.state.dummyData;

    this.setState({ dummyData });
  };

  render() {
    const { handleInput, handleSubmit, handleRemove } = this;
    const { dummyData, name, phone } = this.state;

    return (
      <div className="container">
        <InputBox
          name={name}
          phone={phone}
          onChange={handleInput}
          onSubmit={handleSubmit}
        />
        <PhoneList list={dummyData} deleteItem={handleRemove} />
      </div>
    );
  }
}

export default App;

그럼 이제 handleRemove 함수 코드를 봅시다. handleRemove 함수의 맨 윗줄은 Destructing Assignment, Spread 문법을 모두 사용해서 처음엔 보기 어려울 수 있습니다. 저 코드를 해석해봅시다. 먼저 "[id]: _" 를 통해 제거하고 싶은 아이템을 _라는 변수에 할당합니다. 그리고 Spread 문법을 통해 앞에서 제외한 아이템을 뺀 데이터를 dummyData에 저장합니다. 그런 다음, setState 함수에 dummyData를 넘겨주면 불변성을 위반하지 않고 올바르게 데이터를 변경할 수 있습니다. 이 함수는 PhoneList 컴포넌트에 deleteItem이라는 Props로 전달했으므로 PhoneList 컴포넌트를 수정해봅시다.

import React from "react";
import PhoneItem from "../PhoneItem";
import styled from "styled-components";

const PhoneWrapper = styled.div`
  display: flex;
  flex-direction: column;
  padding-bottom: 50px;
`;

const PhoneList = ({ list, deleteItem }) => {
  return (
    <PhoneWrapper>
      {Object.values(list).map(item => {
        return <PhoneItem {...item} key={item.id} onClick={deleteItem} />;
      })}
    </PhoneWrapper>
  );
};

export default PhoneList;

PhoneList에서 Props를 받고 다시 PhoneItem 컴포넌트에 onClick이라는 Props를 전달해주었습니다. 그럼 이제 PhoneItem 컴포넌트를 수정해보겠습니다.

import React from "react";
import styles from "./PhoneItem.module.scss";

const PhoneItem = ({ id, name, phone, onClick }) => {
  return (
    <div className={styles.phone_item}>
      <div className={styles.phone_item_left}>
        <div className={styles.phone_item_name}>{name}</div>
        <div className={styles.phone_item_phone}>{phone}</div>
      </div>
      <div className={styles.phone_item_right}>
        <button onClick={() => onClick(id)}>삭제</button>
      </div>
    </div>
  );
};

export default PhoneItem;

위와 같이 PhoneItem 컴포넌트의 Button onClick 이벤트 핸들러로 Props로 전달받은 onClick 함수를 지정했습니다. 다만 여기서 "onClick={onClick(id)}"라고 적지 않은 이유는 React에서 이런 이벤트 핸들러로 함수 레퍼런스, 즉 함수 그 자체를 전달해야 하기 때문입니다. 따라서 onClick과 같은 이벤트 속성에 핸들러를 전달할 때에는 "onClick={onClick}"과 같이 소괄호를 제외하고 보냅니다. 다만 여기서는 onClick 함수가 id 파라미터를 받기 때문에 Arrow Function으로 새 함수를 만들고 이를 전달해주는 것입니다.