감정 일기장 만들기 (4) - React에서 배열 사용 ( 데이터 추가, 삭제, 수정 )

HeavyJ·2022년 8월 1일
0

프로젝트의 컴포넌트와 데이터 구조를 생각해보자
<App /> -> <DiaryEditor />
<App /> -> <DiaryList />


App 컴포넌트가 부모, DiaryEditorDiaryList컴포넌트에게 일기 아잉템을 추가해주는게 아니고 StateApp 컴포넌트가 관리하는 형식이다.

조금 더 구체화하면, 아래와 같다.
App [data,setData] -> setData -> DiaryEditor컴포넌트
App [data,setData] -> Data -> DiaryEditor컴포넌트

Data는 부모에서 자식으로, Event는 자식에서 부모로 진행하는 방식이다.

이 방식을 사용하여 App.js에 데이터 형태를 만들어준뒤 데이터를 아래로 이벤트에 해당하는 결과를 위로 전달받는 형태로 만들어보자.

데이터추가

배열로 초기값을 만들어주고, 자식에게 내려줄 data, setData를 생성한다.
DiaryEditor에게 setState를 전달하기 위해 onCreate함수를 만들어서 전달해주고, DiaryList에게 data를 전달하기 위해 {data}를 prop으로 전달해준다.


const [data,setData] = useState([]);

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]);
  };
  
  return(
  	<div className="App">
      <DiaryEditor onCreate={onCreate} />
      <DiaryList diaryList={data} />
    </div>
  );

DiaryEditor.jsonCreate함수를 매개변수로 전달해주고 handleSubmit 함수에 onCreate 함수에 author, content, emotion을 매개변수로 전달해서 setData에 값을 추가해주고 setState는 초기화해준다.

const DiaryEditor = ({ onCreate }) => {
  const authorInput = useRef();
  const contentInput = useRef();
  const [state, setState] = useState({
    author: "",
    content: "",
    emotion: 1,
  });

  const handleChangeState = (e) => {
    console.log(e.target.name);
    console.log(e.target.value);

    setState({
      ...state,
      [e.target.name]: e.target.value,
    });
  };

  const handleSubmit = () => {
    //focus
    if (state.author.length <= 1) {
      authorInput.current.focus();
      return;
    }
    // focus
    if (state.content.length < 5) {
      contentInput.current.focus();
      return;
    }
    onCreate(state.author, state.content, state.emotion);
    console.log(state);
    alert("저장 성공");
    setState({
      author: "",
      content: "",
      emotion: 1,
    });
  };

데이터 삭제

삭제를 하는 경우
App.js에 Id를 매개변수로 하는 onRemove함수를 만들어준다. 추가로 삭제된 아이템을 제외한 아이템들을 리스트에 넣어서 setData해줘 DiaryList.js에 전달해준다.

const onRemove = (targetId) => {
    console.log(`${targetId}가 삭제되었습니다.`);
    const newDiaryList = data.filter((it) => it.id !== targetId);
    setData(newDiaryList);
  };
  
  return{
  	<div className="App">
      <DiaryEditor onCreate={onCreate} />
      <DiaryList onRemove={onRemove} diaryList={data} />
    </div>
  );
  

DiaryList.jsonRemove함수를 prop으로 전달해주고 마찬가지로 DiaryItem에도 onRemove를 전달해준다.

const DiaryList = ({ onRemove, diaryList }) => {
  console.log(diaryList);
  return (
    <div className="DiaryList">
      <h2>일기 리스트</h2>
      <h4>{diaryList.length}개의 일기가 있습니다.</h4>
      <div>
        {diaryList.map((it) => (
          <DiaryItem key={it.id} {...it} onRemove={onRemove} />
          
        ))}
      </div>
    </div>
  );
};

DiaryItem.js에서 삭제버튼을 누르면 handleRemove 함수가 실행되도록 설정해준다.

onst DiaryItem = ({
  onRemove,
  author,
  content,
  emotion,
  created_date,
  id,
}) => {

  const handleRemove = () => {
    console.log(id);
    if (window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)) {
      onRemove(id);
    }
  };

  return (
    <div className="DiaryItem">
      <div className="info">
        <span>
          작성자:{author} | 감정점수:{emotion}
        </span>
        <br />
        <span className="date">{new Date(created_date).toLocaleString()}</span>
      </div>
      <div className="content">
        
      </div>
          <button onClick={handleRemove}>샥제하기</button>
          
    </div>
  );
};
export default DiaryItem;

데이터 수정

수정하는경우

App.js에 추가, 삭제 경우와 마찬가지로 수정 함수를 만들어준다.

  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>
  );

DiaryListonEditprop으로 전달해주고 DiaryItem에도 마찬가지로 전달해준다.

const DiaryList = ({ onEdit, onRemove, diaryList }) => {
  console.log(diaryList);
  return (
    <div className="DiaryList">
      <h2>일기 리스트</h2>
      <h4>{diaryList.length}개의 일기가 있습니다.</h4>
      <div>
        {diaryList.map((it) => (
          <DiaryItem key={it.id} {...it} onRemove={onRemove} onEdit={onEdit} />
          
        ))}
      </div>
    </div>
  );
};

DiaryItem.js

import { useState, useRef } from "react";

const DiaryItem = ({
  onEdit,
  onRemove,
  author,
  content,
  emotion,
  created_date,
  id,
}) => {
  const [isEdit, setIsEdit] = useState(false);

  const toggleIsEdit = () => {
    setIsEdit(!isEdit);
  };

  const [localContent, setLocalContent] = useState(content);
  const localContentInput = useRef();
  const handleRemove = () => {
    console.log(id);
    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>
          작성자:{author} | 감정점수:{emotion}
        </span>
        <br />
        <span className="date">{new Date(created_date).toLocaleString()}</span>
      </div>
      <div className="content">
        {isEdit ? (
          <>
            <textarea
              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;

profile
There are no two words in the English language more harmful than “good job”.

0개의 댓글

관련 채용 정보