Language/React.js

[React] 감정일기장 프로젝트 : EditPage 구현하기

JJcoding 2024. 10. 29. 10:59

Edit Page 구현하기

  • 컴포넌트 구조는
    • Header 컴포넌트
    • Editor 컴포넌트

Edit.jsx의 기능 중 존재하지 않는 페이지에 갔을 경우 코드를 이렇게 구현하게 된다면 에러가 발생한다.

  const getCurrentDiaryItem = () => {
    const currentDiaryItem = data.find(
      (item) => String(item.id) === String(params.id)
    );

    if (!currentDiaryItem) {
      window.alert("존재하지 않는 일기입니다람쥐");
      **nav("/", { replace: true });**
    }

    return currentDiaryItem;
  };

  const currentDiaryItem = getCurrentDiaryItem();
You should call navigate() in a React.useEffect(), 
not when your component is first rendered. 
Error Component Stack
  • useNavigate는 마운트 되고 난 이후에만 실행이 되는 함수이다.
    • BrowserRouter를 통해 사용할 수 있는 훅인데, BrowserRouter도 렌더링이 되지 않은 상태 (모든 컴포넌트가 마운트 돼야 BrowserRouter 컴포넌트도 마운트 되는거니까) 에서 사용하려니까 당연히 안되는 것이다.
  • useEffect를 사용해서 마운트되고 난 후 실행하면 된다. 아래 참고


Edit.jsx

import { useParams, useNavigate } from "react-router-dom";
import Header from "../components/Header";
import Button from "../components/Button";
import Editor from "../components/Editor";
import { useContext, useEffect, useState } from "react";
import { DiaryDispatchContext, DiaryStateContext } from "../App";

const Edit = () => {
  const nav = useNavigate();
  const params = useParams();
  const { onDelete, onUpdate } = useContext(DiaryDispatchContext);
  const data = useContext(DiaryStateContext);
  const [curDiaryItem, setCurDiaryItem] = useState();

  useEffect(() => {
    const currentDiaryItem = data.find(
      (item) => String(item.id) === String(params.id)
    );

    if (!currentDiaryItem) {
      window.alert("존재하지 않는 일기입니다람쥐");
      nav("/", { replace: true });
    }

    setCurDiaryItem(currentDiaryItem);
  }, [params.id, data]);

  const onClickDelete = () => {
    if (
      window.confirm("일기를 정말 삭제할까용가리? 다시 복구되지 않습니다람쥐")
    ) {
      // 확인
      onDelete(params.id);
      nav("/", { replace: true });
    }
  };

  const onSubmit = (input) => {
    if (window.confirm("일기를 정말 수정할까용가리?")) {
      onUpdate(
        params.id,
        input.createdDate.getTime(),
        input.emotionId,
        input.content
      );
      nav("/", { replace: true });
    }
  };

  return (
    <div>
      <Header
        title={"일기 수정하기"}
        leftChild={<Button onClick={() => nav(-1)} text={"< 뒤로 가기"} />}
        rightChild={
          <Button onClick={onClickDelete} text={"삭제하기"} type={"NEGATIVE"} />
        }
      />
      <Editor onSubmit={onSubmit} initData={curDiaryItem} />
    </div>
  );
};

export default Edit;


Editor.jsx

import "./Editor.css";
import EmotionItem from "./EmotionItem";
import Button from "./Button";
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";

...생략

  useEffect(() => {
    if (initData) {
      setInput({
        ...initData,
        createdDate: new Date(Number(initData.createdDate)),
      });
    }
  }, [initData]);

...생략

  • ‘수정하기’를 클릭했을 때 수정하려는 일기의 정보가 Edit 페이지에 이미 바인딩 되어있도록 설정하는 것
  • 완성

Edit Page

 

출처 : 한입 크기로 잘라먹는 리액트