새소식

React ·JS·TS

React/TS study - twitter clone(7)

  • -
    const user = auth.currentUser;
            {user?.displayName ? user.displayName : "Anonymous"}

user의 이름이 있을경우에는 출력해주고 없을경우엔 Anonymous 를 출력해준다

 

해당 if문은 user.displayName이 중복으로 쓰이는데

            {user?.displayName ?? "Anonymous"}

이런식으로 표현이 가능하다.

 

 

    const [avatar, setAvatar] = useState(user?.photoURL);

useState로 사용자 이미지의 URL을 가져온다.

 

 

{Boolean(avatar) ? <AvatarImg src={avatar} /> : <UserLogo src="/user-logo.svg" />}

Boolean을 사용해서 유저가 등록한 이미지가 있는지 확인하기

이미지가 없을 시 기본값이 되는 svg 이미지를 출력하고 이미지가 있으면 사용자의 프로필 사진을 출력한다.

 

 

        <AvatarInput id="avatar" type="file" accept="image/*" />

AvatarUpload를 눌럿을때 숨어있는 input을 노출하기위해 id값 부여하기

 

 

        <AvatarUpload htmlFor="avatar">

input의 id값을 htmlFor="" 를 이용해서 연결해주기

 

 

const onAvatarChange = (e:React.ChangeEvent<HTMLInputElement>) => {};
<AvatarInput onChange={onAvatarChange} id="avatar" type="file" accept="image/*" />

input을 통해 사진을 업로드시 바로 적용하기위해 ChangeEvent 생성해주기

input에 onChange속성 적용하기

 

 

 

        const {files} = e.target;
        if(files && files.length === 1){
            const file = files[0];
        }

파일은 한개만 필요하기때문에 if문으로 검증하기

 

const locationRef = ref(storage, );

파이어베이스에서 strorage instace 넘겨주기

 

 

const locationRef = ref(storage, `avatars/${user?.uid}`);

이후 avatars 폴더안에 유저이미지가 저장되고 파일명은 유저의 아이디가 된다.

유저가 유저이미지를 변경해도 동일한 파일이름으로 업로드가 되어서 덮어쓰기가 진행된다.

 

 

const result = await uploadBytes(locationRef, file);

locationRef로 경로를 설정해주고 file을 넣어준다.

 

 

const avatarUrl = await getDownloadURL(result.ref);

getDownload를 사용하여 해당 URL을  result로 가져온다.

 

 

 

            await updateProfile(user, {
                photoURL : avatarUrl,
            })

유저의 프로필을 업데이트

위와같이 작성하면 Argument of type 'User | null' 이 뜬다 user가 null값일수도 있다는 뜻

 

 

        if(!user) return;

해당부분을 검증하기위해 위에서 유저가 null인지 검증을 해준다

 

 

            setAvatar(avatarUrl);

유저이미지가 state에 할당되어있기 때문에 setAvatar 작성

 

 

 

  const fetchTweets = async () => {};
  useEffect(() => {
    fetchTweets();
  }, []);

realtime으로 작성하지 않기위해서 useEffect에서 fetchTweets를 실행

 

 

  const fetchTweets = async () => {
    const tweetQuery = query(collection(db, "tweets"))
  };

fetchTweets에 query 만들어주기

데이터베이스 인스턴스를 전달, 컬렉션 이름

 

 

        collection(db, "tweets"),
        where("userId", "==", user?.uid),
        orderBy("createdAt", "desc"),
        limit(25)

조건에 맞는 글만 가져오기위해 필터링하기 tweets의 구조를 reference

where(db 아이디값 , 조건, 로그인아이디값)

createdAt의 값으로 역순정렬

최대 25개만 출력되게끔 설정

 

 

 

const snapshot = await getDocs(tweetQuery);

document가져와서 query 전달해주기

getDocs는 query snapshot을 반환해준다.

 

 

const tweets = snapshot.docs.map(doc => {})

원하는 내용을 가져오기 위해서 map 함수를 사용

 

 

    const tweets = snapshot.docs.map(doc => {
        const {tweet, createdAt, userId, username, photo} = doc.data();
    })

무슨 데이터를 가져올지 컬럼명 명시해주기

 

  const [tweets, setTweet] = useState<ITweet[]>([]);
    setTweet(tweets);

useState를 사용해서 사용하고 배열로 호출되는 인터페이스를 갖게하고 빈 배열로 시작하게 한다.

 

 

 

      <Tweets>
        {tweets.map(tweet => <Tweet key={tweet.id} {...tweet} />)}
      </Tweets>

map으로 tweets 데이터를 가져와 tweet 출력하기

 

 

위 코드까지 작성하면 만들려는 쿼리에 인덱스가 필요하다고 오류가 뜬다.

Uncaught (in promise) FirebaseError: The query requires an index. You can create it here:

 

Firestore에 어떤종류의 필터를 사용할지 알려줘야한다.

해당오류의 url을 누르면 index를 설정해줄 수 있는 firebase 사이트로 이동한다.

 

 

자동으로 설정이 되어있는데 저장해주면 된다.

 

 

index 생성이 완료되면 해당 문구를 볼 수 있다.

생성이 완료되면 오류가 뜨지 않고 정상적으로 페이지가 출력된다.

 

 

 

프로필 페이지에서 닉네임을 변경하기 challenge

  const [editing, setEditing] = useState(false);
  const [newUsername, setNewUsername] = useState(user?.displayName);
  const onUpdate = () => {
    setEditing((prev) => !prev);
  };

닉네임을 받는 username과 버튼의 상태를 변경하는 editing을 useState로 선언한다

 

const onUsernameChange = (event : React.ChangeEvent<HTMLInputElement>) => {
    const {
      target : {value},
    } = event ;
    setNewUsername(value);
  };

Input의 value값을 이벤트로 잡아준다

 

const onSubmit = async(event : React.FormEvent) => {
    event.preventDefault();
    if (!user) return;
    if(user?.displayName !== newUsername){
      await updateProfile(user, {
        displayName : newUsername
      });
    }
  }

form태그의 onsubmit을 preventDefault로 초기화 시켜주고

현재 유저의 닉네임과 입력한 닉네임이 다를경우에 db에 저장시켜준다

if(!user)로 유저정보를 검증하고 null값일경우 return

 

{editing ?
      <>
      <NameForm onSubmit={onSubmit}>
        <UserInput type="text" value={newUsername} onChange={onUsernameChange} />
        <ButtonBox>
          <SubmitButton type="submit" value="Update" />
          <UpdateButton onClick={onUpdate}>Cancel</UpdateButton>
        </ButtonBox>
      </NameForm>
      </>
      :
      <>
      <Name>{user?.displayName ?? "Anonymous"}</Name>
      <UpdateButton onClick={onUpdate}>Rename</UpdateButton>
      </>
      }

onClick 이벤트를 editing의 상태로 조건을 걸어서 Rename버튼을 클릭하면 input태그를 노출하여 변경할 수 있게한다.

 

 

 

 

 

'React ·JS·TS' 카테고리의 다른 글

React/TS study - twitter clone(9)  (0) 2023.11.02
React/TS study - twitter clone(8)  (0) 2023.11.02
React/TS study - twitter clone(6)  (0) 2023.10.31
React/TS study - twitter clone(5)  (0) 2023.10.27
React/TS study - twitter clone(4)  (2) 2023.10.27
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.