[React] 방 추가, 삭제 기능 만들기(객체 삽입, 삭제, 수정)
본문 바로가기
더 알아보기/기능

[React] 방 추가, 삭제 기능 만들기(객체 삽입, 삭제, 수정)

by 은돌1113 2022. 5. 24.

방을 추가하고, 삭제 할 수 있는 기능으로써 특정 방을 삭제하면 해당 방의 데이터만 삭제되고 나머지 값들은 자동으로 앞당겨 오도록 구현했다.

 

(목적)

삭제 버튼 클릭 시 해당 행의 방만 삭제 되도록 구현

(예를 들어 방 1 ~ 3까지 있는 상태에서 방 2를 삭제 할 경우 방 2의 값은 삭제되고, 방 3의 값은 방 2로 앞당겨 져야 한다.)


(과정)

  1. 방 하나를 구성하고 있는 객체는 form이다.
  2. 삭제 버튼을 클릭 시 해당 행의 고유값(i)를 삭제 함수(deleteRoom)의 인자(파라미터)로 넘겨준다.
  3. 해당 고유값을 지니고 있는 key 값을 삭제한다. (delete form[`room${i}`];
  4. 삭제된 key 값 다음으로 있는 key 값들의 value를 하나씩 앞당긴다.
    (앞당겨 오는 과정에서는 https://developer-syubrofo.tistory.com/105를 참고했다.
 

[javascript] Object name 변경하기

자바스크립트에서 Object의 value를 유지한 채로 name값을 변경해야 하는 경우가 있다. 구글링을 해서 확인해보니 아래의 링크에 답이 있었다. https://stackoverflow.com/questions/4647817/javascript-object-re..

developer-syubrofo.tistory.com


1. React hook 중 useState를 사용하여 form 객체를 생성한다.

const [form, setForm] = useState({
  count: 1,
  room1: "",
});

- count : 방의 갯수 (방 1이 기본값이기 때문에 초기값에 1을 넣어줬다.)
- room1 : 방 1 정보 (방 1이 기본값이기 때문에 초기값에 넣어줬다.)

 

2. JSX에서는 배열 함수 중 map을 사용하여 방을 출력한다.

<>
  {form.count > 0 &&
    [...Array(form.count)].map((item, i) => {
      return (
        <div key={i + 1}>
          방 {i + 1}
          <input
            type="text"
            placeholder={i + 1}
            value={form[`room${i + 1}`]}
            name={`room${i + 1}`}
            onChange={(e) => {
              setForm({ ...form, [e.target.name]: e.target.value });
            }}
          />
          <button
            onClick={() => {
              deleteRoom(i + 1);
            }}
          >
            삭제
          </button>
        </div>
      );
    })}
  <div onClick={addRoom}>
    <p>+ 방 추가</p>
  </div>
  <br />
  <br />방 갯수 : {form.count}
</>

- form.count > 0 : 꼭 필요한 부분은 아니지만, 예외 처리를 위해 설정했다.

- [...Array(form.count)].map(() => {}) : form.count는 Array가 아니라 Number 타입이기 때문에 form.count만큼 배열을 생성해서 .map을 돌려준다.
- 그 외에는 방을 구성하는 text, input, button(삭제 버튼)과 방 추가하는 div 정도가 있다.

 

3. 방 추가 기능 구현

<div onClick={addRoom}>
  <p>+ 방 추가</p>	
</div>

방 추가 div 클릭 시(onClick) 

const addRoom = () => {
  const number = form.count + 1;

  setForm({
    ...form,
    count: number,
    [`room${number}`]: "",
  });
};

addRoom 함수가 호출되면서 count를 1 증가 시키고, 추가된 방의 정보를 담는 key 값을 추가 해준다.

 

4. 방 삭제 기능 구현

<button
  onClick={() => {
    deleteRoom(i + 1);
  }}
>
  삭제
</button>

삭제 버튼을 클릭 시(onClick) deleteRoom 함수를 호출하게 되는 데
이때 인자로 i + 1을 넘겨준다. 왜냐하면 특정 방을 삭제하는 것이기 때문에 고유값을 넘겨준다.

const deleteRoom = (i) => {
  if (form.count === 1) {
    alert("방 1은 필수사항 입니다.");
    return;
  }

  const newForm = { ...form };

  for (let n = i; n <= newForm.count; n++) {
    if (n === i) {
      delete newForm[`room${n}`];
    } else {
      Object.defineProperty(
        newForm,
        "room" + (n - 1),
        Object.getOwnPropertyDescriptor(newForm, "room" + n)
      );
      delete newForm[`room${n}`];
    }
  }

  setForm({ ...newForm, count: form.count - 1 });
};

- 방 1은 필수사항이기 때문에 if문을 사용해서 처리 해주었다.

- const newForm = {...form}; : form 객체를 전개 연산자를 사용하여 복사 해주었다.
- 삭제하는 방 다음에 있는 방들의 값들을 하나씩 앞당겨야 하기 때문에 for문 조건에 n의 기본값을 i로 설정 해주었다.

- if문은 삭제된 방을 의미하고, else문은 삭제된 방 다음에 있는 방들을 의미한다.


🤔 delete 객체[key 값] : 객체에서 해당 key 값을 찾아 삭제하는 역할

 

🤔 Object.defineProperty(obj, prop, descriptor);

  → obj : 속성을 정의하고자 하는 객체

  → prop : 새로 정의하거나 수정하고자 하는 속성의 이름

  → descriptot : 새로 정의하거나 수정하려는 속성에 대해 기술하는 객체

  > 객체에 직접 새로운 속성을 정의하거나 이미 존재하는 객체를 수정한 뒤 그 객체를 반환한다.

 

🤔 Object.getOwnPropertyDescriptor(obj, prop);

  → obj : 속성을 찾을 대상 객체

  → prop : 설명이 검색될 속성명 (새로운 객체 이름)

  > 속성값에 해당하는 속성 설명자를 반환한다.

 

(출력)

 

(전체 코드)

import { useState } from "react";

const Test = () => {
  const [form, setForm] = useState({
    count: 1,
    room1: "",
  });

  const addRoom = () => {
    const number = form.count + 1;

    if (number >= 10) {
      alert("개인실을 추가 할 수 없습니다.");
      return;
    }

    setForm({
      ...form,
      count: number,
      [`room${number}`]: "",
    });
  };

  const deleteRoom = (i) => {
    if (form.count === 1) {
      alert("방 1은 필수사항 입니다.");
      return;
    }

    const newForm = { ...form };

    for (let n = i; n <= newForm.count; n++) {
      if (n === i) {
        delete newForm[`room${n}`];
      } else {
        Object.defineProperty(
          newForm,
          "room" + (n - 1),
          Object.getOwnPropertyDescriptor(newForm, "room" + n)
        );
        delete newForm[`room${n}`];
      }
    }

    setForm({ ...newForm, count: form.count - 1 });
  };

  return (
    <>
      {form.count > 0 &&
        [...Array(form.count)].map((item, i) => {
          return (
            <div key={i + 1}>
              방 {i + 1}
              <input
                type="text"
                placeholder={i + 1}
                value={form[`room${i + 1}`]}
                name={`room${i + 1}`}
                onChange={(e) => {
                  setForm({ ...form, [e.target.name]: e.target.value });
                }}
              />
              <button
                onClick={() => {
                  deleteRoom(i + 1);
                }}
              >
                삭제
              </button>
            </div>
          );
        })}
      <div onClick={addRoom}>
        <p>+ 방 추가</p>
      </div>
      <br />
      <br />방 갯수 : {form.count}
    </>
  );
};

export default Test;

 

 

 

댓글