CRUD 의 U,D 기능 수정

essential·2023년 7월 16일
0

project

목록 보기
4/4

파일 수정하기 안 됨…………………………..

글 내용 작성 후 post 로 서버에 보내주기(백단에선 update 쿼리문)

뭐가 문제일까? 계속 board_num 에 null 이 들어온다 ,, 백엔드 문제인지 프론트 문제인지 모르겠다 ,,,
미치겠다~~

—결국 해냄 —

수정 전 코드

import { useState } from "react";
import style from "../css/Write.module.css";
import { Link } from "react-router-dom";
import Footer from "../Final/Footer/Footer";
import main_logo from "../images/main_logo.png";
import axios from "axios";
import { useNavigate } from "react-router-dom";

const Modify = () => {
  // 상태 변수 정의
  const [title, setTitle] = useState("");
  const [location, setLocation] = useState("");
  const [price, setPrice] = useState("");
  const [text, setText] = useState("");
  const [file, setFile] = useState(null);
  const [listFile, setListfile] = useState();
  const navigate = useNavigate();

  // input 값 변경 시, 상태 변수 업데이트
  const handleTitleChange = (e) => {
    setTitle(e.target.value);
  };
  const handleLocationChange = (e) => {
    setLocation(e.target.value);
  };

  const [fileDataList, setFileDataList] = useState(); // 서버에 업로드 된 파일 리스트

  var fileList = []; // 업로드 할 파일 리스트 저장

  const onSaveFiles = (e) => {
    const updatefiles = Array.prototype.slice.call(e.target.files); // 파일 이름을 배열 형태로 저장하는 객체
    console.log("updatefiles => " + updatefiles);

    updatefiles.forEach((updatefiles) => {
      console.log("bbb :" + updatefiles);
      fileList.push(updatefiles); // 배열에 push
    });
    setListfile(fileList);
  };

  const onFileUpload = (e) => {
    const formData = new FormData(); // <form></form> 형식의 데이터를 전송하기 위해 주로 사용.
    console.log("fileList=>" + listFile);
    listFile.forEach((file) => {
      formData.append("updatefiles", file);
    });

    console.log(formData);
    if (listFile.length === 0) {
      alert("상품 사진을 하나 이상 등록해 주세요.");
    }

    console.log("id : " + sessionStorage.getItem("id"));
    console.log("title : " + document.getElementById("title").value);
    console.log("location : " + document.getElementById("location").value);
    console.log("price : " + document.getElementById("price").value);
    console.log("content : " + document.getElementById("content").value);

    var boardnum = 0;

    axios
      .post("/updateboard", {
        id: sessionStorage.getItem("id"),
        subject: document.getElementById("title").value,
        location: document.getElementById("location").value,
        price: document.getElementById("price").value,
        content: document.getElementById("content").value,
      })
      .then((res) => {
        console.log(res);
        console.log(res.data);
        console.log("update request");
        boardnum = res.data;
      })
      .catch((e) => {
        console.error(e);
      })
      .then(() => {
        axios
          .post("/updatefile", formData)
          .then((res) => {
            console.log("updatefile request");
            alert("수정이 완료되었습니다!");
            setFileDataList(res.data);
            document.location.href = "/home";
          })
          .catch((e) => {
            console.error(e);
          });
      });
  };

  const handlePriceChange = (e) => {
    setPrice(e.target.value);
  };
  const handleTextChange = (e) => {
    setText(e.target.value);
  };
  const handleAddressSelect = (e) => {
    setFile(e.target.files[0]);
  };

  const handleFormSubmit = (e) => {
    e.preventDefault();
    console.log(title, location, price, text, file);
  };

  return (
    <div className="write_page">
      <h1 sytle="margin:5px;">
        <div className={style.logo_image}>
          <a href="/home">
            <img src={main_logo} alt="logo" width="300px;" height="75px;" />
          </a>
        </div>
      </h1>
      <div className={style.writeContainer}>
        <form className={style.form} onSubmit={handleFormSubmit}>
          <div className={style["input-box"]}>
            <label htmlFor="title">제목</label>
            <input
              type="text"
              id="title"
              value={title}
              onChange={handleTitleChange}
            />
          </div>
          <div className={style[("location-wrapper", "input-box")]}>
            <label htmlFor="location">거래 지역</label>
            <input
              type="text"
              id="location"
              value={location}
              onChange={handleLocationChange}
            />
          </div>
          <div className={(style.fileup, style["input-box"])}>
            <label htmlFor="file">파일 업로드</label>
            <input type="file" id="file" multiple onChange={onSaveFiles} />
          </div>
          <div className={(style.price, style["input-box"])}>
            <label htmlFor="price">상품 가격()</label>
            <div className={style.priceup}>
              <input
                type="number"
                id="price"
                value={price}
                onChange={handlePriceChange}
              />
            </div>
          </div>
          <div className={style["input-box"]}>
            <label htmlFor="content">상세 설명</label>
            <textarea
              id="content"
              value={text}
              onChange={handleTextChange}
              placeholder="상품 소개"
            />
          </div>
          <div className={style["button-container"]}>
            <div id="loginAlert">
              <Link to="#" style={{ textDecoration: "none" }}>
                <button
                  className={style["modify-button"]}
                  onClick={onFileUpload}
                >
                  수정
                </button>
              </Link>
            </div>
            <div
              id="loginAlert"
              onClick={() => {
                alert("작성이 취소되었습니다!");
                navigate("/home");
              }}
            >
              <Link to="/home" style={{ textDecoration: "none" }}>
                <button type="button" className={style["cancel-button"]}>
                  취소
                </button>
              </Link>
            </div>
          </div>
        </form>
      </div>
      <Footer />
    </div>
  );
};

export default Modify;

수정 후 코드

import { useState } from "react";
import style from "../css/Write.module.css";
import { Link } from "react-router-dom";
import Footer from "../Final/Footer/Footer";
import main_logo from "../images/main_logo.png";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { useLocation } from "react-router-dom";

const Modify = () => {
	//추가 된 코드
  const loc = useLocation();
  const board_num = loc.state?.data?.num;
  console.log(loc, board_num);
  // 상태 변수 정의
  const [title, setTitle] = useState("");
  const [location, setLocation] = useState("");
  const [price, setPrice] = useState("");
  const [text, setText] = useState("");
  const [file, setFile] = useState(null);
  const [listFile, setListfile] = useState();
  const navigate = useNavigate();

  // input 값 변경 시, 상태 변수 업데이트
  const handleTitleChange = (e) => {
    setTitle(e.target.value);
  };
  const handleLocationChange = (e) => {
    setLocation(e.target.value);
  };

  const [fileDataList, setFileDataList] = useState(); // 서버에 업로드 된 파일 리스트

  var fileList = []; // 업로드 할 파일 리스트 저장

  const onSaveFiles = (e) => {
    const updatefiles = Array.prototype.slice.call(e.target.files); // 파일 이름을 배열 형태로 저장하는 객체
    console.log("updatefiles => " + updatefiles);

    updatefiles.forEach((updatefiles) => {
      console.log("bbb :" + updatefiles);
      fileList.push(updatefiles); // 배열에 push
    });
    setListfile(fileList);
  };

  const onFileUpload = (e) => {
    const formData = new FormData(); // <form></form> 형식의 데이터를 전송하기 위해 주로 사용.
    listFile.forEach((file) => {
      formData.append("updatefiles", file);
    });
    console.log("fileList=>" + listFile);

    formData.append("num", document.getElementById("num").value); //추가 된 코드
    console.log(formData);
    if (listFile.length === 0) {
      alert("상품 사진을 하나 이상 등록해 주세요.");
    }

    console.log("id : " + sessionStorage.getItem("id"));
    console.log("title : " + document.getElementById("title").value);
    console.log("location : " + document.getElementById("location").value);
    console.log("price : " + document.getElementById("price").value);
    console.log("content : " + document.getElementById("content").value);

    axios
      .post("/updateboard", {
        num: document.getElementById("num").value, 	//추가 된 코드
        id: sessionStorage.getItem("id"),
        subject: document.getElementById("title").value,
        location: document.getElementById("location").value,
        price: document.getElementById("price").value,
        content: document.getElementById("content").value,
      })
      .then((res) => {
        console.log("update request");

        axios
          .post("/updatefile", formData)
          .then((res) => {
            console.log("updatefile request");
            alert("수정이 완료되었습니다!");
            // setFileDataList(res.data);
            document.location.href = "/home";
          })
          .catch((e) => {
            console.error(e);
          });
      })
      .catch((e) => {
        console.error(e);
      });
  };

  const handlePriceChange = (e) => {
    setPrice(e.target.value);
  };
  const handleTextChange = (e) => {
    setText(e.target.value);
  };
  const handleAddressSelect = (e) => {
    setFile(e.target.files[0]);
  };

  const handleFormSubmit = (e) => {
    e.preventDefault();
    console.log(title, location, price, text, file);
  };

  return (
    <div className="write_page">
      <h1 sytle="margin:5px;">
        <div className={style.logo_image}>
          <a href="/home">
            <img src={main_logo} alt="logo" width="300px;" height="75px;" />
          </a>
        </div>
      </h1>
      <div className={style.writeContainer}>
        <form className={style.form} onSubmit={handleFormSubmit}>
          <input type="hidden" id="num" value={board_num} /> //추가 된 코드
          <div className={style["input-box"]}>
            <label htmlFor="title">제목</label>
            <input
              type="text"
              id="title"
              value={title}
              onChange={handleTitleChange}
            />
          </div>
          <div className={style[("location-wrapper", "input-box")]}>
            <label htmlFor="location">거래 지역</label>
            <input
              type="text"
              id="location"
              value={location}
              onChange={handleLocationChange}
            />
          </div>
          <div className={(style.fileup, style["input-box"])}>
            <label htmlFor="file">파일 업로드</label>
            <input type="file" id="file" multiple onChange={onSaveFiles} />
          </div>
          <div className={(style.price, style["input-box"])}>
            <label htmlFor="price">상품 가격()</label>
            <div className={style.priceup}>
              <input
                type="number"
                id="price"
                value={price}
                onChange={handlePriceChange}
              />
            </div>
          </div>
          <div className={style["input-box"]}>
            <label htmlFor="content">상세 설명</label>
            <textarea
              id="content"
              value={text}
              onChange={handleTextChange}
              placeholder="상품 소개"
            />
          </div>
          <div className={style["button-container"]}>
            <div id="loginAlert">
              <Link to="#" style={{ textDecoration: "none" }}>
                <button
                  className={style["modify-button"]}
                  onClick={onFileUpload}
                >
                  수정
                </button>
              </Link>
            </div>
            <div
              id="loginAlert"
              onClick={() => {
                alert("작성이 취소되었습니다!");
                navigate("/home");
              }}
            >
              <Link to="/home" style={{ textDecoration: "none" }}>
                <button type="button" className={style["cancel-button"]}>
                  취소
                </button>
              </Link>
            </div>
          </div>
        </form>
      </div>
      <Footer />
    </div>
  );
};

export default Modify;

board_num 으로 update 를 해줘야하는데 자꾸 board_num 에 null 값이 들어가서 update 가 안 됐다 ,, 그래서 detail 에서 board_num 을 받아오도록 설계를 수정 했다 …
그리고 RequestParam 으로 updatefiles 를 받아주도록 백엔드도 수정했다.

추가 된 코드

const loc = useLocation();
const board_num = loc.state?.data?.num;

 formData.append("num", document.getElementById("num").value);

 num: document.getElementById("num").value,

detail.js

import { Link } from "react-router-dom";
import profile from "../../images/image-07.jpg";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import axios from "axios";

const DetailContentExplain = ({ board }) => {
  const navigate = useNavigate();

  const ContentExplainStyle = {
    margin: "0 auto 30px auto",
    padding: "20px 0 0 0",
    height: "40vh",
    display: "block",
    width: "1300px",
  };

  // 게시자 프로필을 감싸는 div의 스타일
  const ContentExplainUserStyle = {
    display: "flex",
    overflow: "hidden",
    background: "#BBD6FF",
    borderBottom: "0px solid #BBD6FF ",
    borderRadius: "20px 20px 0 0",
    padding: "10px",
    alignItems: "center",
    justifyContent: "flex-start",
    boxSizing: "border-box",
  };

  const UserProfile = {
    width: "40px",
    height: "40px",
    borderRadius: "70%",
    cursor: "pointer",
  };

  const ProfilePtag = {
    justifyContent: "center",
    align: "center",
    width: "100px",
    height: "0px",
    color: "#ffffff ",
    cursor: "pointer",
    lineHeight: "0px",
  };

  // 게시자의 설명문을 감싸는 div의 스타일
  const ContentExplainAreaStyle = {
    border: "1px solid #BBD6FF ",
    borderTop: "1px solid #BBD6FF ",
    height: "80%",
    borderRadius: "0 0 20px 20px",
    boxSizing: "border-box",
  };

  const ExplainPtag = {
    margin: "20px",
    fontSize: "1rem",
    textAlign: "left",
  };

  const ButtonWrap = {
    textAlign: "right",
    margin: "20px 0 0 ",
  };

  const Button = {
    background: "#BBD6FF",
    border: "none",
    color: "white",
    width: "90px",
    height: "30px",
    borderRadius: "3px",
    marginLeft: "10px",
  };

  const Buttonmdf = {
    background: "white",
    border: "1px solid black",
    outline: "0",
    color: "black",
    width: "90px",
    height: "30px",
    borderRadius: "3px",
  };

  const modifyHandler = (e, board) => {
    console.log(board);
    /*
    {
      "num": 1,
      "id": "admin",
      "subject": "ㄷㅈㄹㄷㅈ",
      "location": "ㄹㄷㅈ",
      "content": "ㅈㅂㅇㅈㅂ",
      "price": 321312,
      "addcartcount": 0,
      "viewcount": 13,
      "board_date": "2023-06-25"
  }
    */
    navigate("/modify", { state: { data: board } });
  };

  const handeldelete = () => {
    axios
      .post("/board_del", {
        num: board.num,
      })
      .then((res) => {
        axios
          .post("/file_del", {
            board_num: board.num,
          })
          .then((res) => {
            if (res.data) {
              alert("삭제완료!");
              document.location.href = "/home";
            }
          })
          .catch((e) => {
            console.error(e);
          });
      });
  };

  return (
    <div style={ContentExplainStyle}>
      <div style={ContentExplainUserStyle}>
        <img src={profile} style={UserProfile} alt="" />
        <p style={ProfilePtag}>
          <b>{board.id}</b>
        </p>
      </div>

      <div style={ContentExplainAreaStyle}>
        <h4 style={{ margin: "20px", textAlign: "left" }}>{board.subject}</h4>
        <p style={ExplainPtag}>{board.content}</p>
      </div>
      <div style={ButtonWrap}>
        {/* <Link to="/modify"> */}
        <button
          className="Buttonmdf"
          style={Buttonmdf}
          onClick={(e) => modifyHandler(e, board)}
        >
          수정
        </button>
        {/* </Link> */}
        <button
          className="Button"
          style={Button}
          value="삭제"
          id={board.num}
          onClick={handeldelete}
        >
          삭제
        </button>
      </div>
    </div>
  );
};

export default DetailContentExplain;

사실 모든 구조를 내가 설계했다면 조금 더 쉽게 했을 것 같은데...
남이 한 코드를 수정하다보니 이게 왜 이건지.. 이건 뭔지 해석하고 알아보는데에 시간이 오래 걸렸던 것 같다 .

그래서 form 은 써먹지도 못 하고 props 로 얼렁뚱땅 돌아는가게 수정이 된 것 같은데...
진짜 리액트 너무 어렵다.....

delete 는 handledelete 함수를 써서 api 요청 > 백단에서 delete from~ 쿼리 > 서버에서 board 를 리턴 하게 설계했다! 대신 DB 를 file, board 를 나눠서 설계 했기 때문에 file 에 있는 데이터도 삭제하게끔 해줬다,, 뭔가 더 효율적인 방식이 있을 것 같지만 난 그렇게 했다!

profile
essential

0개의 댓글