[React]React배열 사용하기 - 데이터 수정

Hyoyoung Kim·2022년 8월 20일
0

React TIL

목록 보기
28/40

😎 일기 본문을 수정할 수 있게 구현해보자!

DiaryItem 컴포넌트

import { useState } from "react";

const DiaryItem =({author, content, create_date, emotion,id, onRemove}) => {

    //수정하기 버튼을 눌렀을 때 일기 본무을 수정할 수 있는 폼이 나타나야 한다. 
    const [isEdit, setIsEdit] = useState(false);
    // isEdit은 boolean값을 갖게 된다.
  //(수정중인지 수정중이 아닌지를 boolean타입으로 값을 보관해 놓을 isEdit)
    // isEdit state값이 'true'가 되면 jsx에서 '수정중'으로 간주한다.
    // isEdit state값이 'false'가 되면 jsx에서 '수정중이 아닌 것'으로 간주한다.

    const toggleIsEdit = () => setIsEdit(!isEdit);
    //toggleIsEdit함수는 호출이 되는 순간 원래 isEdit이 갖고 있던 값을 반전시킨다.
    //만약 isEdit값이 true였다면 toggleIsEdit함수는 
  //호출이 되는 순간 isEdit의 값은 false가 된다.


    //수정 입력창에 적은 데이터들을 react에서 state로 핸들링
    const [localContent, setLocalContent] =useState(content)
    //수정버튼을 눌러 수정입력창이 나왔을떄 원래 일기 본문에 적혀져있던 
    //content값이 나오도록 초기값을 설정해둔다. 

    //삭제버튼 눌렀을때 실행되는 함수
    const handleRemove = () => {
        if(window.confirm(`${id}번쨰 일기를 정말 삭제하시겠습니까?`)){
            onRemove(id)
        }
    }

    return <div className="DiaryItem">
        <div className="info">
            <span>
                작성자 : {author} | 감정점수 : {emotion}
            </span>
            <br />
            <span className="date">{new Date(create_date).toLocaleDateString()}</span>
        </div>

        {/* 수정하기 버튼을 눌렀을시 일기 본문의 변화 */}
        {/* isEdit이 true일떄 수정 입력창을 넣어주고 false일떄 원래 content값을 넣어준다. */}
        <div className="content">
            {isEdit ? 
                (<>
                <textarea 
                    value={localContent}
                    onChange={(e)=>{setLocalContent(e.target.value)}}
                />
                </>)  :
                (<>
                {content}
                </>)   
        }
        </div>

        {isEdit ? 
        (<>
        {/* 수정버튼을 눌렀을 때(isEdit의 값이 true일때) 버튼들이 바뀌게 만들어준다.
        (수정취소버튼, 수정완료버튼) */}
        <button onClick={toggleIsEdit}>수정취소</button>
        {/* 수정취소버튼을 두르게 되면 isEdit의 값의 false로 바뀌게 된다. 
        그럼 isEdit의 값이 false일때의 버튼 형태가 나오게 된다. */}
        <button >수정완료</button>
        </>) 
        : (
        <>
        {/* 수정중이 아닐떄의 버튼들 */}
        {/* 삭제버튼 */}
        <button onClick={handleRemove}>삭제하기</button>
        {/* 수정하기 버튼*/}
        <button onClick={toggleIsEdit}>수정하기</button>
        </>
        )}

       
    </div>
}

export default DiaryItem;

수정중일때

수정 중이 아닐때


(문제!) 위의 사진처럼 수정하고 수정취소 버튼을 누르고 다시 수정하기 버튼을 눌렀을 떄의 값이 위의 사진과 같다.

🎃 수정하고 수정취소 버튼을 누르고 다시 수정하기 버튼을 눌렀을 때 원래 content값이 나오도록 코드를 적어보자!

DiaryItem컴포넌트

import { useState } from "react";

const DiaryItem =({author, content, create_date, emotion,id, onRemove}) => {

    const [isEdit, setIsEdit] = useState(false);

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

    const [localContent, setLocalContent] =useState(content)

    //삭제버튼 눌렀을때 실행되는 함수
    const handleRemove = () => {
        if(window.confirm(`${id}번쨰 일기를 정말 삭제하시겠습니까?`)){
            onRemove(id)
        }
    }

    //수정하고 수정취소 버튼을 누르고 다시 수정하기 버튼을 눌렀을 때 
    //원래 content값이 나오도록 하는 함수(초기화시킨다.)
    const handleQuitEdit = () => {
        setIsEdit(false);
        //수정취소버튼을 눌러 수정상태에서 나가는 것이기에 setIsEdit의 값이 false이다. 
        setLocalContent(content);
        //수정 버튼을 눌러 켜진 수정입력창에 적혀져 있는 데이터는 
      //원래 일기 본문에 적혀져있던 데이터로 초기화 해준다. 
    }

    return <div className="DiaryItem">
        <div className="info">
            <span>
                작성자 : {author} | 감정점수 : {emotion}
            </span>
            <br />
            <span className="date">{new Date(create_date).toLocaleDateString()}</span>
        </div>

        <div className="content">
            {isEdit ? 
                (<>
                <textarea 
                    value={localContent}
                    onChange={(e)=>{setLocalContent(e.target.value)}}
                />
                </>)  :
                (<>
                {content}
                </>)   
        }
        </div>

        {isEdit ? 
        (<>
        <button onClick={handleQuitEdit}>수정취소</button>
        {/* 수정 취소버튼이 눌릴때 handleQuitEdit함수가 실행된다. */}
        <button >수정완료</button>
        </>) 
        : (
        <>
        <button onClick={handleRemove}>삭제하기</button>
        <button onClick={toggleIsEdit}>수정하기</button>
        </>
        )}

       
    </div>
}

export default DiaryItem;

결과값

🎃 수정완료 버튼을 눌렀을 때 수정이 되도록 만들어보자~

DiaryItem컴포넌트에 있는 수정완료 이벤트를 App컴포넌트로 보내기 위해서는 데이터를 가지고 있는 App컴포넌트의 수정하는 기능을 하는 함수를 하나 만들어서 DiaryItem컴포넌트까지 보내줘야 한다.

app컴포넌트

import { useState, useRef } from "react";

const DiaryItem =({author, content, create_date, emotion,id, onRemove, onEdit}) => {

    const [isEdit, setIsEdit] = useState(false);

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

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

    //삭제버튼 눌렀을때 실행되는 함수
    const handleRemove = () => {
        if(window.confirm(`${id}번쨰 일기를 정말 삭제하시겠습니까?`)){
            onRemove(id)
        }
    }

    const handleQuitEdit = () => {
        setIsEdit(false);
        setLocalContent(content);
    }

    //수정 완료 버튼을 눌렀을 떄 이벤트를 처리할 함수
    const handleEdit = () =>{

        // 수정한 데이터의 길이가 5글자 이상일때만 수정이 되도록 만들어준다. 
        if(localContent.length<5){
            localContentInput.current.focus();
            return;
        }

        if(window.confirm(`${id}번째 일기를 수정하시겠습니까?`)){
        //예를 눌렀을 떄 onEdit함수 호출
        // App컴포넌트에서 데이터가 수정이 되게 만들기 위해서 onEdit함수를 실행해야 한다. 
        // onEdit함수에 인자로 전달해야하는 값은 id(타겟아이디),localContent(새로 바뀌는 컨텐츠)이다. 
        onEdit(id, localContent); 

        //수정이 완료되었으면 수정폼을 닫아야 한다. 
        toggleIsEdit();
        //수정중이였기에 값이 true였던 isEdit의 값을 false로 반환시켜서 수정폼을 닫는다. 
        }
    }

    return <div className="DiaryItem">
        <div className="info">
            <span>
                작성자 : {author} | 감정점수 : {emotion}
            </span>
            <br />
            <span className="date">{new Date(create_date).toLocaleDateString()}</span>
        </div>

        <div className="content">
            {isEdit ? 
                (<>
                <textarea 
                //textarea를 focus 할 거이기 떄문에 여기다가 레퍼런스 추가
                    ref ={localContentInput}
                    value={localContent}
                    onChange={(e)=>{setLocalContent(e.target.value)}}
                />
                </>)  :
                (<>
                {content}
                </>)   
        }
        </div>

        {isEdit ? 
        (<>
        <button onClick={handleQuitEdit}>수정취소</button>
        {/* 수정 취소버튼이 눌릴때 handleQuitEdit함수가 실행된다. */}
        <button onClick={handleEdit}>수정완료</button>
        {/* 수정 완료 버튼을 눌렀을떄 handleEdit함수가 실행된다. */}
        </>) 
        : (
        <>
        <button onClick={handleRemove}>삭제하기</button>
        <button onClick={toggleIsEdit}>수정하기</button>
        </>
        )}

       
    </div>
}

export default DiaryItem;

DiaryList 컴포넌트

//일기 리스트 컴포넌트

import DiaryItem from "./DiaryItem";

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



export default DiaryList;

DiaryItem 컴포넌트


import { useState, useRef } from "react";

const DiaryItem =({author, content, create_date, emotion,id, onRemove, onEdit}) => {

    const [isEdit, setIsEdit] = useState(false);

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

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

    //삭제버튼 눌렀을때 실행되는 함수
    const handleRemove = () => {
        if(window.confirm(`${id}번쨰 일기를 정말 삭제하시겠습니까?`)){
            onRemove(id)
        }
    }

    const handleQuitEdit = () => {
        setIsEdit(false);
        setLocalContent(content);
    }

    //수정 완료 버튼을 눌렀을 떄 이벤트를 처리할 함수
    const handleEdit = () =>{

        // 수정한 데이터의 길이가 5글자 이상일때만 수정이 되도록 만들어준다. 
        if(localContent.length<5){
            localContentInput.current.focus();
            return;
        }

        if(window.confirm(`${id}번째 일기를 수정하시겠습니까?`)){
        //예를 눌렀을 떄 onEdit함수 호출
        // App컴포넌트에서 데이터가 수정이 되게 만들기 위해서 onEdit함수를 실행해야 한다. 
        // onEdit함수에 인자로 전달해야하는 값은 id(타겟아이디),localContent(새로 바뀌는 컨텐츠)이다. 
        onEdit(id, localContent); 

        //수정이 완료되었으면 수정폼을 닫아야 한다. 
        toggleIsEdit();
        //수정중이였기에 값이 true였던 isEdit의 값을 false로 반환시켜서 수정폼을 닫는다. 
        }
    }

    return <div className="DiaryItem">
        <div className="info">
            <span>
                작성자 : {author} | 감정점수 : {emotion}
            </span>
            <br />
            <span className="date">{new Date(create_date).toLocaleDateString()}</span>
        </div>

        <div className="content">
            {isEdit ? 
                (<>
                <textarea 
                //textarea를 focus 할 거이기 떄문에 여기다가 레퍼런스 추가
                    ref ={localContentInput}
                    value={localContent}
                    onChange={(e)=>{setLocalContent(e.target.value)}}
                />
                </>)  :
                (<>
                {content}
                </>)   
        }
        </div>

        {isEdit ? 
        (<>
        <button onClick={handleQuitEdit}>수정취소</button>
        {/* 수정 취소버튼이 눌릴때 handleQuitEdit함수가 실행된다. */}
        <button onClick={handleEdit}>수정완료</button>
        {/* 수정 완료 버튼을 눌렀을떄 handleEdit함수가 실행된다. */}
        </>) 
        : (
        <>
        <button onClick={handleRemove}>삭제하기</button>
        <button onClick={toggleIsEdit}>수정하기</button>
        </>
        )}

       
    </div>
}

export default DiaryItem;

0개의 댓글