[ JavaScript / React ] 삭제 효과 내보기

2024. 5. 8. 16:56· FRONT-END/└ React

환경 : Visual Studio Code

 

 

    - Ex03.js

import { useState } from "react";
import Jumbotron from "./Jumbotron";


function Ex03(){

    const [items, setItems] = useState(
        [
            {itemNo:1, itemName:"참이슬", itemPrice:1200},
            {itemNo:2, itemName:"처음처럼", itemPrice:1500},
            {itemNo:3, itemName:"새로", itemPrice:1700},
            {itemNo:4, itemName:"좋은데이", itemPrice:1000},
            {itemNo:5, itemName:"청하", itemPrice:2200}
        ]
    );

    //전체 삭제란 비어있는 배열로 state를 덮어쓰기 한다는 것을 의미한다
    //(중요) React는 절대로 state를 고치면 안 된다(새로 만들어 덮어쓰기 해야 함)
    
    //function clearItems(e) {}
    const clearItems = (e) => {
        setItems([]);//삭제
    };

    const deleteItem = (target) => {
        //items에서 item이 아닌 항목만 검색해서 재설정(삭제 효과)
        // const searchItems = items.filter(function(item){
        //     return item.itemNo !== target.itemNo;
        // });
        const searchItems =
                items.filter((item)=>item.itemNo !== target.itemNo);

        setItems(searchItems);//검색 결과로 state를 덮어쓰기
    };

    return(
        <>
            <Jumbotron title="예제3번" content="예제 3번일까나?"></Jumbotron>

            <div className="row mt-4">
                <div className="col">
                    {/* <button className="btn btn-danger" onClick={clearItems}>전체삭제</button> */}
                    <button className="btn btn-danger" onClick={e => clearItems(e)}>전체삭제</button>
                </div>
            </div>

            <div className="row mt-4">
                <div className="col">
                    <table className="table table-hover text-center">
                        <thead>
                            <tr>
                                <td>번호</td>
                                <td>품명</td>
                                <td>가격</td>
                                <td>삭제</td>
                            </tr>
                        </thead>
                        <tbody>
                            {/* 
                                map을 이용한 반복을 할 때
                                생성하는 태그에 제어가 가능한 고유 식별자를 추가(key)

                                안해도 구동은 되지만 지속적인 오류 + 순서 변환 안 됨
                            */}
                            {items.map((item) => (
                                <tr key={item.itemNo}>
                                    <td>{item.itemNo}</td>
                                    <td>{item.itemName}</td>
                                    <td>{item.itemPrice}원</td>
                                    <td>
                                        <button className="btn btn-danger" onClick={e=>deleteItem(item)}> &minus; </button>
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            </div>
        </>
    );
}

export default Ex03;

     (+) 리액트에서 삭제를 진행할 때 state를 고치는 것이 아니라 새로 만들어 덮어쓰기하는 방식으로 진행해야 한다.

     (+) 전체 항목 삭제는 아래와 같은 코드로 진행된다. 

//전체 삭제란 비어있는 배열로 state를 덮어쓰기 한다는 것을 의미한다
//(중요) React는 절대로 state를 고치면 안 된다(새로 만들어 덮어쓰기 해야 함)

//function clearItems(e) {}
const clearItems = (e) => {
    setItems([]);//삭제
};

       (+) state를 빈 배열로 덮어씌워주는 효과

전체삭제 결과

        - 삭제한 것과 같은 효과

        - 새로고침하면 다시 돌아온다

 

     (+) 개별 항목 삭제는 아래와 같은 코드로 진행된다. 

const deleteItem = (target) => {
    //items에서 item이 아닌 항목만 검색해서 재설정(삭제 효과)
    // const searchItems = items.filter(function(item){
    //     return item.itemNo !== target.itemNo;
    // });
    const searchItems =
            items.filter((item)=>item.itemNo !== target.itemNo);

    setItems(searchItems);//검색 결과로 state를 덮어쓰기
};

     (+) 주석의 코드를 줄여 쓴 코드이다. 

     (+) 삭제버튼을 누른 아이템의 번호와 아이템 배열에 있는 아이템 번호가 같지 않은 아이템들만 남길 수 있도록 filer메소를 사용한다.

개별 삭제 결과

 

     (+) 전체 삭제의 경우 간단히 함수 이름만으로도 호출 가능하다 (주석 참고)

{/* <button className="btn btn-danger" onClick={clearItems}>전체삭제</button> */}
<button className="btn btn-danger" onClick={e => clearItems(e)}>전체삭제</button>

 

     (+) 현재 타깃이 된 아이템의 정보를 넘겨주기 위해서 onClick 함수에 화살표함수를 넣어준다 (e=>deleteItem(item))

           각종 오류를 막기 위해 한 번 <tr> 태그가 돌 때마다 어떤 아이템인지 정보를 알 수 있도록 key 값을 설정해준다.

{/* 
    map을 이용한 반복을 할 때
    생성하는 태그에 제어가 가능한 고유 식별자를 추가(key)

    안해도 구동은 되지만 지속적인 오류 + 순서 변환 안 됨
*/}
{items.map((item) => (
    <tr key={item.itemNo}>
        <td>{item.itemNo}</td>
        <td>{item.itemName}</td>
        <td>{item.itemPrice}원</td>
        <td>
            <button className="btn btn-danger" onClick={e=>deleteItem(item)}> &minus; </button>
        </td>
    </tr>
))}

 


이번엔 위의 예제와 비슷하지만 안티 테이블 형식으로 코딩하고, 함수를 더 명확하게 사용해겠다

 

    - Ex04.js

import { useCallback, useState } from "react";
import Jumbotron from "./Jumbotron";

function Ex04() {

    //state
    const [nations, setNations] = useState([
        {no:1, name:"한국", capital:"서울"},
        {no:2, name:"미국", capital:"워싱턴"},
        {no:3, name:"일본", capital:"도쿄"},
        {no:4, name:"중국", capital:"베이징"},
        {no:5, name:"영국", capital:"런던"},
        {no:6, name:"프랑스", capital:"파리"},
        {no:7, name:"독일", capital:"베를린"},
        {no:8, name:"인도", capital:"뉴델리"},
        {no:9, name:"호주", capital:"캔버라"},
        {no:10, name:"스페인", capital:"마드리드"},
    ]);

    //function(callback)
    // - const 함수명 = useCallback(함수, [연관항목]);
    // - 연관항목이 변했을 경우만 함수를 재설정하게 되어 최적화 가능
    // - 연관항목이 없으면 비어있는 배열로 설정
    
    //function deleteNation(target){} 
    //const deleteNation = (target)=>{}; 화살표 함수(arrow function)사용 (this 사용을 막기 위해)
    const deleteNation = useCallback((target)=>{
        const searchResult = nations.filter((nation)=>nation.no !== target.no);
        setNations(searchResult);
    }, [nations]);

    const clearNations = useCallback(()=>{
        setNations([]);
    }, [nations]);

    return (
        <>
            <Jumbotron title="국가 정보" content="목록, 전체삭제, 삭제까지 구현"/>

            <div className="row mt-4">
                <div className="col text-end">
                    <button className="btn btn-danger"
                        onClick={e=>clearNations()}>전체삭제</button>
                </div>
            </div>

            <div className="row mt-4 text-center">
                <div className="col-3">번호</div>
                <div className="col-3">국가</div>
                <div className="col-3">수도</div>
                <div className="col-3">메뉴</div>
            </div>
            <hr/>
            {nations.map((nation)=>(
            <div className="row mt-2 text-center align-items-center" key={nation.no}>
                <div className="col-3">{nation.no}</div>
                <div className="col-3">{nation.name}</div>
                <div className="col-3">{nation.capital}</div>
                <div className="col-3">
                    <button className="btn btn-danger"
                            onClick={e=>deleteNation(nation)}>삭제</button>
                </div>
            </div>
            ))}
        </>
    );
}

export default Ex04;

     (+) const 함수명 = useCallback(함수, [연관항목]);

          - 연관항목이 변했을 경우만 함수 재설정하게 되어 최적화 가능

          - 연관항목이 없으면 비어있는 배열로 설정

const deleteNation = useCallback((target)=>{
    const searchResult = nations.filter((nation)=>nation.no !== target.no);
    setNations(searchResult);
}, [nations]);

const clearNations = useCallback(()=>{
    setNations([]);
}, [nations]);

      

      (+) div 태그로 테이블 느낌 냄

      (+) 글씨를 div태그 중앙에 올 수 있도록 align-items-center를 사용

<div className="row mt-2 text-center align-items-center" key={nation.no}>

 

출력결과

 

 

 

 

 개인 공부 기록용입니다:)

728x90