보라코딩

리액트 CRUD 기능 추가하기2 본문

코딩/REACT

리액트 CRUD 기능 추가하기2

new 보라 2023. 8. 1. 15:47
DELETE

 

 

Carlist.js

 

1. 표의 각 행에 버튼 만들기

    버튼 필드 : 자동차에 대한 링크인 _links.self.href

    filterable과 sortable은 false (정렬과 필터링 필요 없기 때문)

 

const columns = [
  {field:'brand', headerNmae: 'Brand', width: 200},
  {field:'model', headerNmae: 'Model', width: 200},
  {field:'color', headerNmae: 'Color', width: 200},
  {field:'year', headerNmae: 'Year', width: 150},
  {field:'price', headerNmae: 'Price', width: 150},

  {
    field: '_links.self.href',
    headerNmae: '',
    sortable: false,
    filterable: false,
    renderCell: row =>
    <button
      onClick={() => onDelClick(row.id)}>Delete
    </button>
  }
];

 

 

 

 

2. onDelClick 함수 구현하기 전

    우선 useEffect 후크에서 fetch 메서드 가져와야 함!

       ㄴ 자동차 삭제 후 업데이트된 목록 보여주려면 fetch 호출 필요

 

useEffect(() => {
  fetchCars();
}, []);

  const fetchCars = () => {
    fetch(SERVER_URL + 'api/cars')
      .then((response) => response.json())
      .then((data) => setCars(data._embedded.cars))
      .catch((err) => console.error(err));
  }

 

 

 

3. onDelClick 함수 구현하기

  const onDelClick = (url) => {
    if (window.confirm("진짜 삭제하시겠습니까??")){
      fetch(url, {method: 'DELETE'})
      .then(response => {
        if(response.ok){
          fetchCars();
          setOpen(true);
        }
        else {
          alert("뭔가 잘못 되었다~~~")
        }
      })
      .catch(err => console.error(err))
    }
  }

 

 

 

4. 알림메시지 구현하기

import { Snackbar } from "@mui/material";
const [open, setOpen] = useState(false);
 return (
    <div style={{height:500, width:'100%'}}>
      <DataGrid
        rows={cars}
        columns={columns}
        disableSelectionOnClick={true}
        getRowId={row => row._links.self.href}/>

        <Snackbar
          open={open}
          autoHideDuration={2000}
          onClose={() => setOpen(false)}
          message="Car 삭제되었습니다!"
          />
    </div>    
  );

 

 

 

5. 삭제 작업 잘 진행되었는지 응답상태 확인

     ㄴ onDelClick에서 if문으로 response 확인

 

if(response.ok){
          fetchCars();
          setOpen(true);
        }
        else {
          alert("뭔가 잘못 되었다~~~")
        }

 

 

 

 

 

 

 

 

 

 

CREATE

 

 

AddCar.js (components 폴더 밑에 새로 생성)

 

1. MUI Dialog 컴포넌트에 필요한 import문 추가

2. useState 후크를 이용해 모든 자동차 필드 포함하는 상태 선언

3. 대화상자 폼 닫고 여는 두개 함수 추가

4. return 문에 Dialog 컴포넌트 추가

   ㄴ 필드에는 값이 저장될 상태의 이름과 같은 값을 가진 name 사용해야 함

 

import React, {useState} from "react";
import { Dialog, DialogActions, DialogContent, DialogTitle, Fab } from "@mui/material";


function AddCar(props){

    const [open, setOpen] = useState(false);
    const [car, setCar] = useState({
        brand: '',
        model: '',
        color: '',
        year: '',
        fuel: '',
        price: ''
    });

    const handleClickOpen = () => {
        setOpen(true);
    };

    const handleClose = () => {
        setOpen(false);
    };

    const handleChange = (event) => {
        setCar({...car, [event.target.name]: event.target.value});
    }

    const handleSave = () => {
        props.addCar(car);
        handleClose();
    }

    return(
        <div>
            <button onClick={handleClickOpen}>New Car</button>
            <Dialog open={open} onClose={handleClose}>
                <DialogContent>
                    <input placeholder="Brand" name="brand"
                    value={car.brand} onChange={handleChange}/>
                    <br/>
                    <input placeholder="Model" name="model"
                    value={car.model} onChange={handleChange}/>
                    <br/>
                    <input placeholder="Color" name="color"
                    value={car.color} onChange={handleChange}/>
                    <br/>
                    <input placeholder="Year" name="year"
                    value={car.year} onChange={handleChange}/>
                    <br/>
                    <input placeholder="Price" name="price"
                    value={car.price} onChange={handleChange}/>
                    <br/>
                </DialogContent>
                <DialogActions>
                    <button onClick={handleClose}>Cancel</button>
                    <button onClick={handleSave}>Save</button>
                </DialogActions>
            </Dialog>
        </div>
    );
}

export default AddCar;

 

 

 

 

5. Carlist.js 에서 addCar 함수 구현

 

import AddCar from "./AddCar.js";
const addCar = (car) => {
  fetch(SERVER_URL + 'api/cars',
  {
    method: 'POST',
    headers: { 'Content-Type':'application/json' },
    body: JSON.stringify(car)
  })
  .then(response => {
    if(response.ok){
      fetchCars();
    }
    else {
      alert('Something went wrong!');
    }
  })
  .catch(err => console.error(err))
}

 

 

 

6. Carlist.js에 return문에 AddCar 컴포넌트 추가

     addCar 함수를 프롭으로 addCar 컴포넌트에 전달

 

return (
    <React.Fragment>
      <AddCar addCar={addCar} />
      <div style={{height:500, width:'100%'}}>
      <DataGrid
        rows={cars}
        columns={columns}
        disableSelectionOnClick={true}
        getRowId={row => row._links.self.href}/>

        <Snackbar
          open={open}
          autoHideDuration={2000}
          onClose={() => setOpen(false)}
          message="Car 삭제되었습니다!"
          />
      </div>  
    </React.Fragment>  
  );

 

 

 

 

 

 

 

 

 

 

 

 

UPDATE

 

 

 

1. components 폴더 내에 EditCar.js 새 파일 만든다.

2. return 문에서 편집 대화상자 폼 렌더링한다

 

import React, { useState } from 'react';
import { Dialog, DialogActions, DialogContent, DialogTitle } from "@mui/material";

function EditCar(props) {

    const [open,setOpen] = useState(false);
    const [car, setCar] = useState({
        brand: '', model: '', color: '',
        year: '', fuel: '', price: ''
    });

    // 모달 폼 열기
    const handleClickOpen = () => {
        setCar({
            brand: props.data.row.brand,
            model: props.data.row.model,
            color: props.data.row.color,
            year: props.data.row.year,
            fuel: props.data.row.fuel,
            price: props.data.row.price
        })
        setOpen(true);
    }

    const handleClose = (event) => {
        setCar({...car,
        [event.target.name]: event.target.value});
    }

    // 자동차 업데이트하고 모달폼 닫음
    const handleSave = () => {
        props.updateCar(car, props.data.id);
        handleClose();
    }

    const handleChange = (event) => {
        setCar({...car,
        [event.target.name]: event.target.value});
    }



    return (
        <div>
            <button onClick={handleClickOpen}>Edit</button>
            <Dialog open={open} onClose={handleClose}>
                <DialogTitle>Edit Car</DialogTitle>
                <DialogContent>
                    <input placeholder='Brand' name='brand'
                    value={car.brand} onChange={handleChange}/>
                    <br/>
                    <input placeholder='Model' name='model'
                    value={car.model} onChange={handleChange}/>
                    <br/>
                    <input placeholder='Color' name='color'
                    value={car.color} onChange={handleChange}/>
                    <br/>
                    <input placeholder='Year' name='year'
                    value={car.year} onChange={handleChange}/>
                    <br/>
                    <input placeholder='Price' name='price'
                    value={car.price} onChange={handleChange}/>
                    <br/>
                </DialogContent>
                <DialogActions>
                    <button onClick={handleClose}>Cancel</button>
                    <button onClick={handleSave}>Save</button>
                </DialogActions>
            </Dialog>
        </div>
    )
}

export default EditCar;

 

 

 

 

3. 자동차 데이터 업데이트 하기 위헤 Carlist.js에서 const updateCar 새함수 만든다.

    EditCar도 import

 

import EditCar from "./EditCar.js";

const updateCar = (car, link) => {
  fetch(link,
    {
      method: 'PUT',
      headers: { 'Content-Type':'application/json'},
      body: JSON.stringify(car)
    })
    .then(response => {
      if (response.ok) {
        fetchCars();
      }
      else {
        alert('Something went wrong!');
      }
    })
    .catch(err => console.error(err))
}

 

 

 

4. EditCar 컴포넌트를 표 열에 추가


  const columns = [
    {field: 'brand', headerName: 'Brand', width: 200},
    {field: 'model', headerName: 'Model', width: 200},
    {field: 'color', headerName: 'Color', width: 200},
    {field: 'year', headerName: 'Year', width: 150},
    {field: 'price', headerName: 'Price', width: 150},
    {
      field: '_links.car.href',
      headerName: '',
      sortable: false,
      filterable: false,
      renderCell: row =>
      <EditCar
        data={row}
        updateCar={updateCar} />
    },
    {
      field: '_links.self.href',
      headerName: '',
      sortable: false,
      filterable: false,
      renderCell: row =>
          <button
            onClick={() =>
            onDelClick(row.id)}>Delete
          </button>
    }
 
  ];

 

 

 

5. EditCar.js에서 handleClickOpen 함수 수정한다.

6. 마지막으로 handleSave 함수 수정해서 props를 통해 updateCar 함수 호출한다

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

데이터를 CSV로 내보내기!

 

 

1. import

import { DataGrid, GridToolbarContainer } from "@mui/x-data-grid";
 
import { GridToolbarExport, gridClasses } from "@mui/x-data-grid";

 

 

2. MUI 컴포넌트로 Export 버튼 렌더링하는 toolbar 컴포넌트 만들기

function CustomToolbar(){
  return (
    <GridToolbarContainer
        className={gridClasses.toolbarContainer}>
          <GridToolbarExport />
        </GridToolbarContainer>
  );
}

 

 

 

3. return에서 components에 Toolbar 추가하기

return (
    <React.Fragment>
      <AddCar addCar={addCar} />
      <div style={{height:500, width:'100%'}}>
      <DataGrid
        rows={cars}
        columns={columns}
        disableSelectionOnClick={true}
        getRowId={row => row._links.self.href}
        components={{ Toolbar: CustomToolbar }}
        />

        <Snackbar
          open={open}
          autoHideDuration={2000}
          onClose={() => setOpen(false)}
          message="Car 삭제되었습니다!"
          />
      </div>  
    </React.Fragment>  
  );