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>2021년 1월 30일</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)을 삭제하면 중간에 있던 다른 것들까지 한번에 삭제가 됨.
왜 이런 현상이 일어나지...??
안녕하세요! 😊 작성하신 코드를 확인해보니, "중간에 있는 글을 삭제할 때 그 뒤에 있는 글들도 같이 삭제되는 현상"은 splice 메서드의 사용법을 잘못 이해한 것 때문에 발생한 문제로 보입니다. 하나씩 문제를 분석하고 해결책을 설명드릴게요!
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]
삭제 버튼 클릭 시 작성한 코드:
let copy = [...글제목];
copy.splice(i, i + 1); // 문제 발생 지점
글제목변경(copy);
여기서 splice(i, i + 1)은 다음과 같이 동작합니다:
i: 삭제를 시작할 인덱스.i + 1: 삭제할 요소의 개수. 즉, 삭제를 시작하는 인덱스(i)부터 i + 1개의 요소를 삭제합니다.
예를 들어, i = 3일 때:
그래서 중간의 다른 요소들까지 삭제가 되는 것입니다.
splice의 두 번째 인자(deleteCount)를 항상 1로 설정해야 중간의 요소 하나만 삭제됩니다. 수정된 코드는 다음과 같습니다:
let copy = [...글제목];
copy.splice(i, 1); // i번 인덱스부터 1개 요소만 삭제
글제목변경(copy);
이렇게 하면 클릭한 인덱스(i)의 요소 하나만 삭제되고, 나머지 요소는 영향을 받지 않습니다.
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>2021년 1월 30일</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;
splice의 두 번째 인자: 삭제할 개수를 잘못 설정해서 중간의 다른 요소들까지 삭제된 것이 원인입니다.splice(i, 1)로 삭제할 개수를 1로 고정하세요.추가로 궁금한 점이 있다면 언제든 질문해주세요! 😊
사실 처음에는 splice 말고 pop으로 처리하려고 했었다.
그 때는 copy.pop(삭제값); 라고 썼는데 정상적으로 동작하지 않음.
그건 왜 그래?
좋은 질문이에요! 😊 작성한 copy.pop(삭제값)이 정상적으로 동작하지 않은 이유는 pop() 메서드의 동작 방식 때문이에요. 이를 하나씩 설명해드릴게요.
pop() 메서드의 동작 방식pop()은 배열의 마지막 요소를 제거하는 메서드입니다. 사용법은 아래와 같아요:
let arr = [1, 2, 3, 4, 5];
arr.pop(); // 마지막 요소(5)를 제거
console.log(arr); // [1, 2, 3, 4]
pop()은 인자를 받지 않습니다.pop(삭제값)과 같이 인자를 넘겨도 아무런 효과가 없어요.pop()을 사용했을 때의 문제점작성한 코드:
let copy = [...글제목];
copy.pop(삭제값); // 마지막 요소가 아닌 특정 인덱스를 삭제하려고 시도
글제목변경(copy);
이 경우 pop()은 삭제값이라는 인자를 무시하고, 배열의 마지막 요소만 제거합니다. 따라서 삭제값이 아무리 설정되어 있어도 지정한 인덱스를 삭제할 수 없고 항상 마지막 요소만 삭제됩니다.
pop()은 특정 인덱스를 삭제하는 데 적합하지 않으므로, splice() 메서드를 사용해야 합니다. 예를 들어, 특정 인덱스를 삭제하려면 아래와 같이 작성해야 합니다:
let copy = [...글제목];
copy.splice(삭제값, 1); // 삭제값 번째 인덱스부터 1개 요소를 삭제
글제목변경(copy);
pop()으로 처리하려면?pop()으로 특정 요소를 삭제하려면 배열을 조작해야 하는데, 이는 비효율적입니다. 예를 들어:
let copy = [...글제목];
let targetIndex = 삭제값; // 삭제하고 싶은 인덱스
copy = copy.slice(0, targetIndex).concat(copy.slice(targetIndex + 1));
글제목변경(copy);
이렇게 하면 특정 인덱스를 기준으로 배열을 나눠서 새로운 배열을 만든 다음 삭제할 요소를 제외한 결과를 반환할 수 있습니다. 하지만 이렇게까지 할 필요 없이 splice()를 사용하는 것이 가장 간단하고 효과적이에요.
pop()은 항상 배열의 마지막 요소만 제거하기 때문에 특정 인덱스를 삭제하는 데 사용할 수 없습니다.splice() 메서드를 사용하는 것이 가장 간단한 해결책입니다.splice(i, 1)로 작성하면 i번째 요소를 정확히 삭제할 수 있습니다.