반응형
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

데이터 수정하기 본문

인프런, 유데미/한입 크기로 잘라 먹는 리액트

데이터 수정하기

5_hyun 2022. 5. 25. 17:32
반응형
import { useRef, useState } from "react";

const DiaryItem = ({
  onEdit,
  onRemove,
  author,
  content,
  created_date,
  emotion,
  id,
}) => {
  // isEdit가 false면 평소, true면 수정하는 상태
  const [isEdit, setIsEdit] = useState(false);
  const toggleIsEdit = () => setIsEdit(!isEdit);
  // 기본값 content로 해야 원래 값에서 수정 가능
  const [localContent, setLocalContent] = useState(content);
  const localContentInput = useRef();

  const handleRemove = () => {
    if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
      onRemove(id);
    }
  };
  // 수정하다가 취소하고 다시 수정하면 처음에 취소한 그대로 있음
  const handleQuitEdit = () => {
    setIsEdit(false);
    setLocalContent(content);
  };

  const handleEdit = () => {
    if (localContent.length < 5) {
      localContentInput.current.focus();
      return;
    }
    if (window.confirm(`${id}번 째 일기를 수정하시겠습니까?`)) {
      onEdit(id, localContent);
      toggleIsEdit();
    }
  };

  return (
    <div className="DiaryItem">
      <div className="info">
        <span className="anuthor_info">
          작성자 : {author} | 감정점수 : {emotion}
        </span>
        <br />
        <span className="date">{new Date(created_date).toLocaleString()}</span>
      </div>
      <div className="content">
        {isEdit ? (
          <>
            <textarea
              ref={localContentInput}
              value={localContent}
              onChange={(e) => setLocalContent(e.target.value)}
            />
          </>
        ) : (
          <>{content}</>
        )}
      </div>
      {isEdit ? (
        <>
          <button onClick={handleQuitEdit}>수정 취소</button>
          <button onClick={handleEdit}>수정 완료</button>
        </>
      ) : (
        <>
          <button onClick={handleRemove}>삭제하기</button>
          <button onClick={toggleIsEdit}>수정하기</button>
        </>
      )}
    </div>
  );
};

export default DiaryItem;

우선 [isEdit, setIsEdit]을 만들었다. 그래서 isEdit가 false면 평소, true면 수정하는 상태이다. 

 

그리고 삼항 연산자를 이용해서 버튼을 만들어줬다.

삼항 연산자는 isEdit의 상태에 따라서 다르게 나타나도록 해줬다.

 

isEdit가 false면 삭제하기와 수정하기가 나온다.

삭제하기는 전 글에 올린거 그대로했다.

수정하기는 toggleIsEdit를 만들고 setIsEdit를 활용하여 isEdit의 상태를 바꿔줬다.

 

그리고 isEdit가 true면, 즉 수정하기 버튼을 누른 상태이면 수정 취소와 수정 완료가 나온다.

수정 취소는 handleQuitEdit를 만들어 setIsEdit를 활용해 isEdit를 false로 만들고 setLocalContent를 다시 원래 값으로 돌려놨다.

수정 완료는 handleEdit를 만들어 만약 5자 미만으로 수정하면 수정창에 focus를 하여 다시 수정하도록 했다. 이때 focus를 하기 위해서는 useRef를 활용했다. 5자 이상이면 일기를 수정하겠나는 메시지를 띄우고 사용자가 확인을 누르면 App.js에서 만든 onEdit 함수를 이용해 id와 변경된 내용인 localContent를 보내준다. 그리고 toggleIsEdit()으로 isEdit의 상태를 바꿔준다.

=> 리엑트 특성상 데이터는 위에서 아래, 이벤트는 아래에서 위로 간다. 그렇기에 수정 완료 이벤트를 DiartItem에서 App까지 전달하기 위해서는 데이터를 가지고 있는 App에 수정하는 기능을 가진 함수(onEdit)을 만들어서 DiaryItem까지 보내줘야한다.

 

-App.js

import { useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";

const App = () => {
  const [data, setData] = useState([]);

  const dataId = useRef(0);

  const onCreate = (author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      id: dataId.current,
    };
    dataId.current += 1;
    setData([newItem, ...data]);
  };

  const onRemove = (targetId) => {
    const newDiaryList = data.filter((it) => it.id !== targetId);
    setData(newDiaryList);
  };

  const onEdit = (targetId, newContent) => {
    setData(
      data.map((it) =>
        it.id === targetId ? { ...it, content: newContent } : it
      )
    );
  };

  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate} />
      <DiaryList onEdit={onEdit} onRemove={onRemove} diaryList={data} />
    </div>
  );
};

export default App;

따라서 App.js에 onEdit를 만들고 data를 수정하여 내용을 업데이트한다.

반응형

'인프런, 유데미 > 한입 크기로 잘라 먹는 리액트' 카테고리의 다른 글

React에서 API 호출하기  (0) 2022.05.26
Lifecycle 제어하기  (0) 2022.05.26
데이터 삭제하기  (0) 2022.05.25
데이터 추가하기  (0) 2022.05.24
리스트 렌더링  (0) 2022.05.24
Comments