splice/pop 사용법

이윤희·2024년 12월 24일

React/Next 일기

목록 보기
4/52

react 로 input을 받아 데이터를 처리하는 연습 중
input에서 전송버튼을 누르면 글이 하나 등록되고, 글의 삭제하기 버튼을 누르면 글이 지워지도록 만드는 게 목표.

내가 작성한 코드 :

import { useState } from "react";
import "./App.css";
function Appex() {

    let [글제목, 글제목변경] = useState(['여자 코트 추천', '딱대 코트 추천', '강남 우동 맛집','남자 코트 추천','딱자 코트 추천','수자 코트 추천']);
    let [modal, setModal] = useState(false);
    let [따봉, 따봉변경] = useState([0,0,0]);
    let [title, setTitle] = useState(0);
    let [입력값, 입력값변경] = useState('');
    // let [삭제값, 삭제값변경] = useState(0);

// '2021년 1월 30일', '2024년 12월 6일', '2023년 2월 13일'
    return (
      <div className="App">
        <div>
            <h4 className="black-nav">ReactBlog</h4>
        </div>
        <button onClick={()=>{
            // 정렬도 복사본 만들어서 해야함
            let cpy = [...글제목];
            cpy.sort();
            글제목변경(cpy);
        }}>가나다순 정렬</button>


        {
        글제목.map((a, i)=> {
            
            return(
            <div className="list">
                <h4 onClick={()=>{
                    // 클릭했을 때 true 로 바꿔줘야함
                    setModal(true);
                    setTitle(i);
                    modal == true ? setModal(false) : null;
                }}> {a}    <span onClick={(e)=>{
                    e.stopPropagation()
                    let cpy = [...따봉];
                    cpy[i] = cpy[i] + 1;// 따봉이 아니라 cpy를 바꿔야했다!!
                    따봉변경(cpy);
                }}> 👍 </span>
                {" "}
                {따봉[i]}</h4>
                <p>2021130</p>
                <button onClick={()=>{
                    let copy = [...글제목];

                    copy.splice(i,i+1);
                    // copy.pop(삭제값);
                    // 몇번째인덱스만 삭제되어 버리네... 뭘로해야하지?
                    // 오 pop말고 splice로 하니까 됨!!!

                    // 중간에 있는 걸 지우면 뒤에꺼까지 같이 날라가 버리는데 이건 뭐지?
                    글제목변경(copy);
                }}>삭제하기</button>
            </div> 
            )
        })
    }

    <input onChange={(e)=>{ //이벤트객체 e
        입력값변경(e.target.value);
        // console.log(입력값) e.target.value 이 안의 값
        // cf. 왜 한박자 늦게되나? > state변경은 비동기로 처리하기 때문에 냅두고 다음줄 먼저 실행함!!
        // 그래서 다음줄을 먼저 실행함.

       
        // onChange랑 같은거 onInput
    }}
    />
     <button onClick={()=>{
            let cpy = [...글제목];
            cpy.push(입력값); 
            // cpy.unshift(입력값); < 이것도 되던데 이건 배열 맨앞에 추가함
            글제목변경(cpy);
        }}>글쓰기</button>

    */}
    { modal == true ? <Modal 글제목={글제목} 글제목변경={글제목변경} title={title} /> : null 
    }
      </div>

    );
  }
  function Modal(props){
    let copy = [...props.글제목];
    copy[0] = '딱대 코트 완성';
    copy[1] = '딱대 코트 완성';
    copy[2] = '딱대 코트 완성';


    return(
        <div className="modal">
            <h4>{props.글제목[props.title]}</h4>      
            <p>날짜</p>
            <p>상세내용</p>
            <button onClick={()=>{
                props.글제목변경(copy);
            }}>글수정</button>
        </div>
    )
  }

export default Appex;

여기서 궁금한 점이 생김:
삭제하기 버튼을 눌렀을때 정상적으로 삭제가 되기는 하는데
0부터 6까지 인덱스가 있다면 중간것(예를 들면 3)을 삭제하면 중간에 있던 다른 것들까지 한번에 삭제가 됨.
왜 이런 현상이 일어나지...??




GPT

안녕하세요! 😊 작성하신 코드를 확인해보니, "중간에 있는 글을 삭제할 때 그 뒤에 있는 글들도 같이 삭제되는 현상"은 splice 메서드의 사용법을 잘못 이해한 것 때문에 발생한 문제로 보입니다. 하나씩 문제를 분석하고 해결책을 설명드릴게요!


1. splice 메서드의 사용법 복습

splice는 배열에서 특정 요소를 제거하거나 추가하는 데 사용됩니다. 메서드의 기본 형태는 다음과 같습니다:

array.splice(startIndex, deleteCount);
  • startIndex: 배열에서 변경을 시작할 인덱스.
  • deleteCount: startIndex부터 몇 개의 요소를 삭제할지.

예시:

let arr = [1, 2, 3, 4, 5];
arr.splice(2, 1); // 2번 인덱스부터 1개 요소 삭제
console.log(arr); // [1, 2, 4, 5]

2. 작성한 코드에서의 문제점

삭제 버튼 클릭 시 작성한 코드:

let copy = [...글제목];
copy.splice(i, i + 1); // 문제 발생 지점
글제목변경(copy);

여기서 splice(i, i + 1)은 다음과 같이 동작합니다:

  • i: 삭제를 시작할 인덱스.
  • i + 1: 삭제할 요소의 개수.

즉, 삭제를 시작하는 인덱스(i)부터 i + 1개의 요소를 삭제합니다.
예를 들어, i = 3일 때:

  • 삭제는 3번 인덱스부터 시작하고,
  • 4개(3 + 1)의 요소가 삭제됩니다.

그래서 중간의 다른 요소들까지 삭제가 되는 것입니다.


3. 문제 해결

splice의 두 번째 인자(deleteCount)를 항상 1로 설정해야 중간의 요소 하나만 삭제됩니다. 수정된 코드는 다음과 같습니다:

let copy = [...글제목];
copy.splice(i, 1); // i번 인덱스부터 1개 요소만 삭제
글제목변경(copy);

이렇게 하면 클릭한 인덱스(i)의 요소 하나만 삭제되고, 나머지 요소는 영향을 받지 않습니다.


4. 수정된 전체 코드

import { useState } from "react";
import "./App.css";

function Appex() {
  let [글제목, 글제목변경] = useState([
    "여자 코트 추천",
    "딱대 코트 추천",
    "강남 우동 맛집",
    "남자 코트 추천",
    "딱자 코트 추천",
    "수자 코트 추천",
  ]);
  let [modal, setModal] = useState(false);
  let [따봉, 따봉변경] = useState([0, 0, 0, 0, 0, 0]); // 따봉 배열 크기 수정
  let [title, setTitle] = useState(0);
  let [입력값, 입력값변경] = useState("");

  return (
    <div className="App">
      <div>
        <h4 className="black-nav">ReactBlog</h4>
      </div>
      <button
        onClick={() => {
          let cpy = [...글제목];
          cpy.sort();
          글제목변경(cpy);
        }}
      >
        가나다순 정렬
      </button>

      {글제목.map((a, i) => {
        return (
          <div className="list" key={i}>
            <h4
              onClick={() => {
                setModal(true);
                setTitle(i);
              }}
            >
              {a}{" "}
              <span
                onClick={(e) => {
                  e.stopPropagation();
                  let cpy = [...따봉];
                  cpy[i] = cpy[i] + 1;
                  따봉변경(cpy);
                }}
              >
                👍
              </span>{" "}
              {따봉[i]}
            </h4>
            <p>2021130</p>
            <button
              onClick={() => {
                let copy = [...글제목];
                copy.splice(i, 1); // i번 인덱스부터 1개만 삭제
                글제목변경(copy);
              }}
            >
              삭제하기
            </button>
          </div>
        );
      })}

      <input
        onChange={(e) => {
          입력값변경(e.target.value);
        }}
      />
      <button
        onClick={() => {
          let cpy = [...글제목];
          cpy.push(입력값);
          글제목변경(cpy);
        }}
      >
        글쓰기
      </button>

      {modal == true ? (
        <Modal
          글제목={글제목}
          글제목변경={글제목변경}
          title={title}
        />
      ) : null}
    </div>
  );
}

function Modal(props) {
  let copy = [...props.글제목];
  copy[0] = "딱대 코트 완성";
  copy[1] = "딱대 코트 완성";
  copy[2] = "딱대 코트 완성";

  return (
    <div className="modal">
      <h4>{props.글제목[props.title]}</h4>
      <p>날짜</p>
      <p>상세내용</p>
      <button
        onClick={() => {
          props.글제목변경(copy);
        }}
      >
        글수정
      </button>
    </div>
  );
}

export default Appex;

5. 정리

  1. splice의 두 번째 인자: 삭제할 개수를 잘못 설정해서 중간의 다른 요소들까지 삭제된 것이 원인입니다.
  2. 수정 방법: splice(i, 1)로 삭제할 개수를 1로 고정하세요.
  3. React 상태 관리: 항상 state를 업데이트할 때 원본 배열을 복사한 후 변경하세요.

추가로 궁금한 점이 있다면 언제든 질문해주세요! 😊




사실 처음에는 splice 말고 pop으로 처리하려고 했었다.
그 때는 copy.pop(삭제값); 라고 썼는데 정상적으로 동작하지 않음.
그건 왜 그래?



GPT

좋은 질문이에요! 😊 작성한 copy.pop(삭제값)이 정상적으로 동작하지 않은 이유는 pop() 메서드의 동작 방식 때문이에요. 이를 하나씩 설명해드릴게요.


1. pop() 메서드의 동작 방식

pop()배열의 마지막 요소를 제거하는 메서드입니다. 사용법은 아래와 같아요:

let arr = [1, 2, 3, 4, 5];
arr.pop(); // 마지막 요소(5)를 제거
console.log(arr); // [1, 2, 3, 4]
  • 특징: pop()은 인자를 받지 않습니다.
  • 즉, 항상 배열의 마지막 요소만 제거합니다.
  • 따라서 pop(삭제값)과 같이 인자를 넘겨도 아무런 효과가 없어요.

2. pop()을 사용했을 때의 문제점

작성한 코드:

let copy = [...글제목];
copy.pop(삭제값); // 마지막 요소가 아닌 특정 인덱스를 삭제하려고 시도
글제목변경(copy);

이 경우 pop()삭제값이라는 인자를 무시하고, 배열의 마지막 요소만 제거합니다. 따라서 삭제값이 아무리 설정되어 있어도 지정한 인덱스를 삭제할 수 없고 항상 마지막 요소만 삭제됩니다.


3. 해결 방법

pop()은 특정 인덱스를 삭제하는 데 적합하지 않으므로, splice() 메서드를 사용해야 합니다. 예를 들어, 특정 인덱스를 삭제하려면 아래와 같이 작성해야 합니다:

let copy = [...글제목];
copy.splice(삭제값, 1); // 삭제값 번째 인덱스부터 1개 요소를 삭제
글제목변경(copy);

4. 특정 요소를 pop()으로 처리하려면?

pop()으로 특정 요소를 삭제하려면 배열을 조작해야 하는데, 이는 비효율적입니다. 예를 들어:

let copy = [...글제목];
let targetIndex = 삭제값; // 삭제하고 싶은 인덱스
copy = copy.slice(0, targetIndex).concat(copy.slice(targetIndex + 1));
글제목변경(copy);

이렇게 하면 특정 인덱스를 기준으로 배열을 나눠서 새로운 배열을 만든 다음 삭제할 요소를 제외한 결과를 반환할 수 있습니다. 하지만 이렇게까지 할 필요 없이 splice()를 사용하는 것이 가장 간단하고 효과적이에요.


5. 정리

  • pop()항상 배열의 마지막 요소만 제거하기 때문에 특정 인덱스를 삭제하는 데 사용할 수 없습니다.
  • 특정 인덱스를 삭제하려면 splice() 메서드를 사용하는 것이 가장 간단한 해결책입니다.
  • splice(i, 1)로 작성하면 i번째 요소를 정확히 삭제할 수 있습니다.

0개의 댓글