/EDIT 구현

조뮁·2023년 1월 15일

React

목록 보기
28/34
post-thumbnail
  • 수정페이지 경로 설정
    No routes matched location "/edit/3"
// App.js
return (
    <DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider value={{ onCreate, onEdit, onRemove }}>
        <BrowserRouter>
          <div className="App">
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path="/new" element={<New />} />
                // edit 컴포넌트에서도 path variable 설정해서 edit/1 과 같이 이동할 수 있도록 설정
              <Route path="/edit/:id" element={<Edit />} />
              <Route path="/diary/:id" element={<Diary />} />
            </Routes>
          </div>
        </BrowserRouter>
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );
  • path variable 받기
// Edit.js
import { useNavigate, useParams } from "react-router-dom";

const Edit = () => {
  const navigate = useNavigate();
  // 현재 전달받은 id 꺼내기
  const { id } = useParams();
  console.log(id);

  return (
    <div>
      <h1>Edit</h1>
    </div>
  );
};

export default Edit;

  • 수정 전 일기 데이터 가져오기
    - 원본 데이터 : App.js > data state
    - useContext 사용하여 컨텍스트로부터 데이터 받아오기
    (1) 모든 일기 데이터 가져오기
// Edit.js
import { useNavigate, useParams } from "react-router-dom";
import { useContext } from "react";
import { DiaryStateContext } from "../App";

const Edit = () => {
  const navigate = useNavigate();
  // 현재 전달받은 id 꺼내기
  const { id } = useParams();

  const diaryList = useContext(DiaryStateContext);
  console.log(diaryList);

  return (
    <div>
      <h1>Edit</h1>
    </div>
  );
};

export default Edit;

(2) 수정할 id값과 동일한 일기 데이터 가져오기

// Edit.js
import { useNavigate, useParams } from "react-router-dom";
import { useContext, useEffect } from "react";
import { DiaryStateContext } from "../App";

const Edit = () => {
  const navigate = useNavigate();
  // 현재 전달받은 id 꺼내기
  const { id } = useParams();

  const diaryList = useContext(DiaryStateContext);
  console.log(diaryList);

  // edit 컴포넌트가 mount 되었을 때 수정하려는 일기데이터 가져오기
  // id가 변하거나 diaryList가 변할때만 일기 데이터 꺼내오기
  useEffect(() => {
    if (diaryList.length >= 1) {
      const targetDiary = diaryList.find(
        // target의 id와 수정페이지의 id가 동일하도록 Int로 변경해줌
        (it) => parseInt(it.id) === parseInt(id)
      );
      console.log(targetDiary);
    }
  }, [id, diaryList]);

  return (
    <div>
      <h1>Edit</h1>
    </div>
  );
};

export default Edit;

만약, 존재하지 않는 id를 호출할경우

동일하게 edit 페이지가 뜨는데, 이는 잘못된 접근이기 때문에 home으로 돌려보내야함

// Edit.js
useEffect(() => {
    if (diaryList.length >= 1) {
      const targetDiary = diaryList.find(
        // target의 id와 수정페이지의 id가 동일하도록 Int로 변경해줌
        (it) => parseInt(it.id) === parseInt(id)
      );
      console.log(targetDiary);

      if (!targetDiary) {
        // 존재하지 않는 id를 불러올 경우 undefined(falsy)한 값으로 인식
        navigate("/", { replace: true });
      }
    }
  }, [id, diaryList]);

일기 수정하기

원본 데이터 저장

// Edit.js
// target Diary Data 저장
const [originData, setOriginData] = useState();

useEffect(() => {
  if (diaryList.length >= 1) {
    const targetDiary = diaryList.find(
      // target의 id와 수정페이지의 id가 동일하도록 Int로 변경해줌
      (it) => parseInt(it.id) === parseInt(id)
    );
    console.log(targetDiary);

    if (targetDiary) {
      setOriginData(targetDiary);
    } else {
      // 존재하지 않는 id를 불러올 경우 undefined(falsy)한 값으로 인식
      navigate("/", { replace: true });
    }
  }
}, [id, diaryList]);

Diary 컴포넌트 리턴

// Edit.js
const Edit = () => {
  const navigate = useNavigate();
  // 현재 전달받은 id 꺼내기
  const { id } = useParams();
  const diaryList = useContext(DiaryStateContext);

  // target Diary Data 저장
  const [originData, setOriginData] = useState();

  // edit 컴포넌트가 mount 되었을 때 수정하려는 일기데이터 가져오기
  // id가 변하거나 diaryList가 변할때만 일기 데이터 꺼내오기
  useEffect(() => {
    if (diaryList.length >= 1) {
      const targetDiary = diaryList.find(
        // target의 id와 수정페이지의 id가 동일하도록 Int로 변경해줌
        (it) => parseInt(it.id) === parseInt(id)
      );
      console.log(targetDiary);

      if (targetDiary) {
        setOriginData(targetDiary);
      } else {
        // 존재하지 않는 id를 불러올 경우 undefined(falsy)한 값으로 인식
        navigate("/", { replace: true });
      }
    }
  }, [id, diaryList]);
	// originData가 있으면 DiaryEditor을 return함
  return <div>{originData && <DiaryEditor />}</div>;
};

// 원래 있던 return <div></div>는 삭제

export default Edit;

원본 데이터 추가

// Edit.js
// originData가 있으면 DiaryEditor을 return함
  return (
    <div>
      {/* Diary 컴포넌트에서는 isEdit과 originData를 받아서 수정폼으로 변환시켜줌 */}
      {originData && <DiaryEditor isEdit={true} originData={originData} />}
    </div>
  );

DiaryEditor.js 수정

  • 원본 데이터 불러오기
// App.js
// Edit.js 에서 넘겨준 props 받기
const DiaryEditor = ({isEdit, originData}) => {
  // edit페이지에서 DiaryComponent를 랜더하면 isEdit과 originData가 변경됨 -> 이 때만 실행
  useEffect(() => {
    if (isEdit) {
      // 원래 작성된 데이터로 변경
      setDate(getStringDate(new Date(parseInt(originData.date))));
      setslctEmotionId(originData.emotion);
      setContent(originData.content);
    }
  }, [isEdit, originData]);

  return (
    <div>
      {/* 1. header */}
      <MyHeader
        // isEdit === true 면 헤더text 수정
        headText={isEdit ? "일기 수정하기" : "새 일기쓰기"}
        leftChild={
          <MyButton text={"< 뒤로가기"} onClick={() => navigate(-1)}></MyButton>
        }
        ...
        )
}

수정 완료

const DiaryEditor = ({ isEdit, originData }) => {
  // onEdit 디스패치 함수도 불러오기
  const { onCreate, onEdit } = useContext(DiaryDispatchContext);
  
  // 작성완료 함수
  const handleSubmit = () => {
    if (content.length < 1) {
      contentRef.current.focus();
      return;
    }

    if (
      window.confirm(
        isEdit ? "일기를 수정할까요?" : "새로운 일기를 추가할까요?"
      )
    ) {
      // 수정이 아닐 경우 onCrate 실행
      if (!isEdit) {
        onCreate(date, content, slctEmotionId);
      } else {
        // 수정일 경우 onEdit 실행
        onEdit(originData.id, date, content, slctEmotionId);
      }
    }
    navigate("/", { replace: true });
  };
  
  return (
    <div>
      {/* 1. header */}
      <MyHeader
        // isEdit === true 면 헤더text 수정
        headText={isEdit ? "일기 수정하기" : "새 일기쓰기"}
        leftChild={
          <MyButton text={"< 뒤로가기"} onClick={() => navigate(-1)}></MyButton>
        }
      ></MyHeader>
...
        <section>
          <div className="control_box">
            <MyButton text={"취소하기"} onClick={() => navigate(-1)} />
// isEdit에 따라 버튼명 수정
            <MyButton
              text={isEdit ? "수정하기" : "작성 완료"}
              type={"positive"}
              onClick={handleSubmit}
            />
          </div>
        </section>
      </div>
    </div>
  );
  
}

0개의 댓글