<aside> 💡 세부 목표

배열을 이용한 React의 List에 아이템을 동적으로 수정 해보기 With 조건부 렌더링

</aside>

App.js

map을 이용해 해당 id와 data에 들어있는 item 리스트를 순회해 비교해서 같은 경우 새로운 content를 업데이트 시킨다.

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

function 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
    }
    console.log("newItem : ", newItem);
    dataId.current += 1;
    setData([newItem, ...data,]) //원래 데이터 를 가져오고 새로운 item은 최상단에 나오도록 함
  }

  const onDelete = (targetId)=>{
    console.log(`${targetId}가 삭제되었습니다.`);
    // filter 이용해서 삭제할 Id에 대한 일기 빼고 해당 객체 리스트 가져옴
    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} onDelete={onDelete} diaryList={data}/>
    </div>
  );
}

export default App;

DiaryList.js

import DiaryItem from "./DiaryItem";

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

DiaryList.defaultProps = {
    diaryList: [],
}

export default DiaryList;

DiaryItem.js

import { useRef, useState } from 'react';
const DiaryItem = ({ onEdit, onDelete, author, content, created_date, emotion, id }) => {

    const [isEdit, setIsEdit] = useState(false); // 현재 수정중인지 수정중이 아닌지 확인용
    const  toggleIsEdit = () => setIsEdit(!isEdit);  // true, false를 toggle 시키기

    const [localContent, setLocalContent] = useState(content);
    const localContentInput = useRef();

    const handleRemove = ()=>{
        if(window.confirm(`${id}번째 일기를 정말 삭제하시겠습니까?`)){
            onDelete(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).toLocaleDateString()}</span>
        </div>
        <div className="content">
            {isEdit ? (
                <>
                    <textarea ref={localContentInput} 
                    value={localContent} onChange={(e)=>setLocalContent(e.target.value)}>

                    </textarea>
                </>
             ):(
                <>{content}</>
             )}
        </div>
        {isEdit ? (
                <>
                    <button onClick={handleQuitEdit}>수정 취소</button>
                    <button onClick={handleEdit}>수정 완료</button>
                </>
             ):(
                <>
                    <button onClick={handleRemove}>삭제하기</button>
                    <button onClick={toggleIsEdit}>수정하기</button>
                </>
             )}
    </div>
};

export default DiaryItem;