Hyemimi·2022년 7월 16일
0
post-thumbnail

작성자에게만 보이는 delete, edit 버튼 만들기

폼의 버튼 또는 엔터를 눌러 firestore에 보내준 데이터인 creatorId(보냈을 시점의 userObj.id)와 현재 유저의 uid(현재 시점의 userObj.id)를 가져와, 비교해서 같으면 delete와 edit 버튼이 보이도록 한다.

[App.js(일부 생략)]

const [userObj, setUserObj] = useState(null);

  useEffect(() => {
    auth.onAuthStateChanged((user) => {
      if (user) {
        setIsloggedIn(true);
        setUserObj(user);
      } else {
        setIsloggedIn(false);
      }
      setInit(true);
    });
  }, []);

위와 같이 useEffect를 이용해서 사용자가 로그인할 때 user 정보를 userObj에 넣어주었고 결과적으로 Home.js에 props로 넘겼을 때,

[Home.js(일부 생략)]


const onSubmit = async (event) => {
    event.preventDefault();
    try {
      await addDoc(collection(db, "tweets"), {
        text: tweet,
        createdAt: Date.now(),
        creatorId: userObj.uid,
      });
    } catch (e) {
      console.error(e);
    }

    setTweet("");
  };

firestore에 넘겨줄 creatorId는 작성한 사용자의 아이디를 넘겨주어야 하므로 폼을 제출할 때 실행되는 함수인 onSubmit에서 userObj.uid로 할당되었다.

그리고 트윗 하나하나를 가져와 보여주어야 하므로(firestore에서 데이터를 꺼내오는 과정은 이전 포스팅), tweets라는 배열을 순회하도록 map()함수를 이용하고, map()함수를 통해 보여줄 내용은 길어질 우려가 있으므로 따로 컴포넌트를 생성해준다.

[Tweet.js]

import { db } from "fbase";
import {doc, updateDoc, deleteDoc}from "firebase/firestore";
import React from "react";

const Tweet = ({ key, tweetObj, isOwner }) => {
  const onDeleteClick = async () => {
    const ok = window.confirm
    ("Are you sure you want to delete this tweet?");
    if (ok) {
      await deleteDoc(doc(db, "tweets", `${tweetObj.id}`));
    }
  };
  return (
    <div>
      <h4>{tweetObj.text}</h4>
      {isOwner && (
        <>
          <button onClick={onDeleteClick}>
    Delete Tweet</button>
          <button>Edit Tweet</button>
        </>
      )}
    </div>
  );
};
export default Tweet;

tweetObj는 map()함수에 의해 얻은tweets배열의 요소 중 하나인tweet이고, (props로 받음)

isOwner는 ,

isOwner={tweet.creatorId === userObj.uid}

다음과 같이 트윗을 생성한 user의 uid와 현재 사용자 uid를 비교해서 true값 or false값을 띤다.
isOwner가 true이면

{isOwner && (
        <>
          <button onClick={onDeleteClick}>
  Delete Tweet</button>
          <button>Edit Tweet</button>
        </>
      )}

다음과 같이 삭제/편집 버튼을 보여주는 것이다.

삭제 버튼을 누르면 삭제하기

그렇다면 위의 코드에서, 버튼을 누르면 삭제하는 onDeleteClick 함수에 대해서 알아보자.

const onDeleteClick = async () => {
    const ok = window.confirm
    ("Are you sure you want to delete this tweet?");
    if (ok) {
      await deleteDoc(doc(db, "tweets", `${tweetObj.id}`));
    }
  };

firestore의 데이터를 삭제하기 위해서는,
위와 같이 doc()deleteDoc를 감싸면 된다.
doc의 세번째 인자는 문서의 id이다.

useEffect(() => {
    const q = query(collection(db, "tweets"), 
                    orderBy("createdAt", "desc"));
    onSnapshot(q, (snapshot) => {
      const tweetArr = snapshot.docs.map((document) => ({
        id: document.id,
        ...document.data(),
      }));
      console.log(tweetArr);
      setTweets(tweetArr);
    });
  }, []);

위의 코드에서 document.id가 바로 우리가 트윗을 삭제하기 위해 사용할 경로와도 같다. 이 id가 doc()의 세 번째 인자로 들어간다.
React를 처음 배우며 느낀 점은, id 사용이 정말 중요하다

edit 하기

1. 버튼을 누르면 edit 상태가 되도록 설정

const [editing, setEditing] = useState(false);
const toggleEditing = () => {
    setEditing(!editing);
  }; 

toggleEditing 함수를 onClick 이벤트로 부여한다.

<button onClick={toggleEditing}>Edit Tweet</button>

2. edit 상태일때 > tweetObj.text가 그대로 보이며 글자를 적을 수 있는 상태

우선 글자를 지우고 적는 상태 관리를 하기 위해서 useState를 사용한다.

const [newTweet, setNewTweet] = useState(tweetObj.text);

편집을 위해 적는 글자들은 newTweet이며, 초기값은 원본이여야 하므로 tweetObj.text다.

<form>
            <input
              type="text"
              placeholder="edit your tweet"
              onChange={onChange}
              value={newTweet}
              required
            ></input>
            <input onClick={onSubmit}
type="submit" value="Update Tweet" />
          </form>

위의 폼은 편집을 위한 폼이다.
value는 newTweet, 따라서 onChange 이벤트에 의해서 newTweet의 값을 바꾸어준다면 입력에 따라 폼의 값이 바뀌는 상태관리가 가능할 것이다.
또한 'Update Tweet'라고 쓰여져 있는 폼의 버튼을 누른다면 onSubmit 함수가 실행되며 이에 따라 firestore상의 data가 수정될 것이다.

const onChange = (event) => {
    setNewTweet(event.target.value);
  };

onChange 함수까지 만들어주었다.

 const onSubmit = async (event) => {
    event.preventDefault();
    await updateDoc(doc(db, "tweets", `${tweetObj.id}`), 
                    { text: newTweet });
    setEditing(false);
  };

onSubmit 함수는 위와 같이 폼의 제출 버튼을 누르면 text 값을 newTweet 값으로 바꾸어 주는 과정이며, setEditing을 통해 편집 상태를 false로 바꾸어준다.

3. !edit 상태일때 > 편집 상태가 아니므로 그대로 tweetObj.text와 작성자라면 delete버튼과 edit 버튼을 볼 수 있음

<div>
      {editing ? (
        <>
          <form>
            <input
              type="text"
              placeholder="edit your tweet"
              onChange={onChange}
              value={newTweet}
              required
            ></input>
            <input onClick={onSubmit} type="submit" 
value="Update Tweet" />
          </form>
          <button onClick={toggleEditing}>Cancel</button>
        </>
      ) : (
        <>
          <h4>{tweetObj.text}</h4>
          {isOwner && (
            <>
              {" "}
              <button onClick={onDeleteClick}>Delete Tweet
                </button>
              <button onClick={toggleEditing}>Edit Tweet
                </button>
            </>
          )}
        </>
      )}
    </div>

조건부 렌더링을 이용해 editing이 true이면 편집 폼과 취소버튼(편집 상태를 false로 만듦)을 보여주고, editing이 false라면 tweetObj.text와 작성자라면 delete버튼과 edit 버튼을 보여줄 것이다.

profile
암냠냠

0개의 댓글