Profile.jsx
import { styled } from "styled-components";
import { auth } from "../firebase";
import { useState } from "react";
const Wrapper = styled.div`
display: flex;
align-items: center;
flex-direction: column;
gap: 20px;
`;
const AvatarUpload = styled.label`
width: 80px;
overflow: hidden;
height: 80px;
border-radius: 50%;
background-color: #1d9bf0;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
svg {
width: 50px;
}
`;
const AvatarImg = styled.img`
width: 100%;
`;
const AvatarInput = styled.input`
display: none;
`;
const Name = styled.span`
font-size: 22px;
`;
const Profile = () => {
const user = auth.currentUser; //현재 인증된 유저의 정보를 가져온다.
//인정된 유저가 있으면, 유저의 프로필 URL을 state에 저장
const [avatar, setAvatar] = useState(user?.photoURL);
return (
<Wrapper>
<AvatarUpload htmlFor="avatar">
{/* 아바타가 있으면 본인의 프로필사진 출력하고 */}
{avatar ? (
<AvatarImg src={avatar} />
) : (
// 아바타 사진이 없을 경우 출력되는 이미지
<svg
fill="currentColor"
viewBox="0 0 20 20"
aria-hidden="true"
>
<path d="M10 8a3 3 0 100-6 3 3 0 000 6zM3.465 14.493a1.23 1.23 0 00.41 1.412A9.957 9.957 0 0010 18c2.31 0 4.438-.784 6.131-2.1.43-.333.604-.903.408-1.41a7.002 7.002 0 00-13.074.003z" />
</svg>
)}
</AvatarUpload>
<AvatarInput id="avatar" type="file" accept="image/*" />
{/* 유저의 이름이 없을 경우 익명으로 표시하기 */}
<Name>{user?.displayName ?? "익명"}</Name>
</Wrapper>
);
};
export default Profile;
나는 프로필과 이름이 둘 다 설정되어있으므로 이렇게 잘 나온다.
홍길동의 프로필은 이렇게 나온다.
만약 프로필 사진을 업데이트하고 싶으면?
import { styled } from 'styled-components';
import { auth, storage } from '../firebase';
import { useState } from 'react';
import { getDownloadURL, ref, uploadBytes } from 'firebase/storage';
import { updateProfile } from 'firebase/auth';
...
export default function Profile() {
const user = auth.currentUser;
const [avatar, setAvatar] = useState(user?.photoURL);
const onAvatarChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const { files } = e.target;
if (!user) return;
if (files && files.length === 1) {
const file = files[0];
const locationRef = ref(storage, `avatars/${user?.uid}`);
const result = await uploadBytes(locationRef, file);
const avatarUrl = await getDownloadURL(result.ref);
setAvatar(avatarUrl);
await updateProfile(user, {
photoURL: avatarUrl,
});
}
};
return (
<Wrapper>
...
<AvatarInput onChange={onAvatarChange} id='avatar' type='file' accept='image/*' />
<Name>{user?.displayName ?? 'Anonymous'}</Name>
</Wrapper>
);
}
홍길동의 프로필을 업데이트해보자
홍길동의 프로필을 클릭하면 이미지를 선택할 수 있다.
그 중에 어피치를 선택해서 업데이트 했다.
https://blog.naver.com/drv983/223262006492
그리고 프로필에 내가 작성한 트윗만 출력하기
Profile.jsx 에 추가한다.
const Tweets = styled.div`
display: flex;
width: 100%;
flex-direction: column;
gap: 10px;
`;
import { styled } from "styled-components";
import { auth, db } from "../firebase";
import { useEffect, useState } from "react";
import { getDownloadURL, uploadBytes } from "firebase/storage";
import { updateProfile } from "firebase/auth";
import {
collection,
getDocs,
limit,
orderBy,
query,
where,
} from "firebase/firestore";
import Tweet from "../components/Tweet";
const Wrapper = styled.div`
display: flex;
align-items: center;
flex-direction: column;
gap: 20px;
`;
const AvatarUpload = styled.label`
width: 80px;
overflow: hidden;
height: 80px;
border-radius: 50%;
background-color: #1d9bf0;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
svg {
width: 50px;
}
`;
const AvatarImg = styled.img`
width: 100%;
`;
const AvatarInput = styled.input`
display: none;
`;
const Name = styled.span`
font-size: 22px;
`;
const Tweets = styled.div`
display: flex;
width: 100%;
flex-direction: column;
gap: 10px;
`;
const Profile = () => {
const user = auth.currentUser; //현재 인증된 유저의 정보를 가져온다.
//인정된 유저가 있으면, 유저의 프로필 URL을 state에 저장
const [avatar, setAvatar] = useState(user?.photoURL);
const [tweets, setTweets] = useState([]);
// 내가 쓴 트윗만 가져오는 쿼리
const fetchTweets = async () => {
const q = query(
collection(db, "tweets"),
where("userId", "==", user?.uid),
orderBy("createdAt", "desc"),
limit(25)
);
const snapshot = await getDocs(q);
const tweets = snapshot.docs.map((doc) => {
const { tweet, createdAt, userId, username, photo } = doc.data();
return {
tweet,
createdAt,
userId,
username,
photo,
id: doc.id,
};
});
setTweets(tweets);
};
useEffect(() => {
fetchTweets();
}, []);
//아바타 변경 시
const onAvatarChange = async (e) => {
const { files } = e.target;
if (!user) return;
if (files && files.length === 1) {
const file = files[0];
const locationRef = ref(storage, `avatars/${user?.uid}`);
const result = await uploadBytes(locationRef, file);
const avatarUrl = await getDownloadURL(result.ref);
setAvatar(avatarUrl);
await updateProfile(user, {
photoURL: avatarUrl,
});
}
};
return (
<Wrapper>
<AvatarUpload htmlFor="avatar">
{/* 아바타가 있으면 본인의 프로필사진 출력하고 */}
{avatar ? (
<AvatarImg src={avatar} />
) : (
// 아바타 사진이 없을 경우 출력되는 이미지
<svg
fill="currentColor"
viewBox="0 0 20 20"
aria-hidden="true"
>
<path d="M10 8a3 3 0 100-6 3 3 0 000 6zM3.465 14.493a1.23 1.23 0 00.41 1.412A9.957 9.957 0 0010 18c2.31 0 4.438-.784 6.131-2.1.43-.333.604-.903.408-1.41a7.002 7.002 0 00-13.074.003z" />
</svg>
)}
</AvatarUpload>
<AvatarInput
onChange={onAvatarChange}
id="avatar"
type="file"
accept="image/*"
/>
{/* 유저의 이름이 없을 경우 익명으로 표시하기 */}
<Name>{user?.displayName ?? "익명"}</Name>
<Tweets>
{tweets.map((tweet) => (
<Tweet key={tweet.id} {...tweet} />
))}
</Tweets>
</Wrapper>
);
};
export default Profile;
콘솔에 이러한 오류가 뜨면 저 링크를 클릭해서
색인을 저장한다. (몇 분 소요됨)
컬렉션이 생성이 완료되면
프로필 페이지에서는 본인이 작성한 트윗만 확인할 수 있다.
본인 프로필명을 수정하는 버튼을 만들어서 수정하기
Profile.jsx에 state를 추가한다.
const [isUpdate, setIsUpdate] = useState(false); //프로필 수정
그리고 이름 표시하는 태그를 수정한다.
저장 버튼을 클릭하면 updateName 함수가 실행된다.
{/* 유저의 이름이 없을 경우 익명으로 표시하기 */}
<Name>{user?.displayName ?? "익명"}</Name>
{isUpdate ? (
<>
<input type="text" placeholder="새이름..." />
<button onClick={updateName}>저장</button>
</>
) : (
<button onClick={() => setIsUpdate(true)}>수정</button>
)}
//프로필 이름 수정 함수
const updateName = () => {
setIsUpdate(false);
};
input의 내용이 변경되면 setName으로 저장한다.
const [name, setName] = useState(""); //프로필 이름 수정 시
{/* 유저의 이름이 없을 경우 익명으로 표시하기 */}
<Name>{user?.displayName ?? "익명"}</Name>
{isUpdate ? (
<>
<input
onChange={(e) => setName(e.target.value)}
type="text"
placeholder="새이름..."
/>
<button onClick={updateName}>저장</button>
</>
) : (
<button onClick={() => setIsUpdate(true)}>수정</button>
)}
updateName 함수를 수정한다.
//프로필 이름 수정 함수
const updateName = async () => {
if (!name || name.trim().length < 2) return;
if (!user) return;
await updateProfile(user, {
displayName: name,
});
setIsUpdate(false);
};
이제 홍길동 이름을 변경할거임
홍길순으로 변경된것이 확인된다.
'FRONTEND > React' 카테고리의 다른 글
[React-BookStore] firebase 인증 기능 추가하기 - 이메일/비밀번호 (회원가입/로그인) (1) | 2023.12.11 |
---|---|
[Nwitter-Fire] 호스팅 (1) | 2023.12.11 |
[Nwitter-Fire] 파이어 스토어 스토리지 사용설정 / 트윗 저장/이미지 저장 / 타임라인 생성 및 실시간 업데이트/ 트윗 삭제 (0) | 2023.12.08 |
[Nwitter-Fire] 새로운 깃허브 인증 추가 (0) | 2023.12.08 |
[Nwitter-Fire] ProtectedRoute 비인증시 블록 및 로그인 기능 (1) | 2023.12.08 |