기록하는 개발자

[React, Firebase] TwitterCloneCoding 4.0 Edit Profile 본문

Web/React

[React, Firebase] TwitterCloneCoding 4.0 Edit Profile

밍맹030 2021. 10. 18. 22:47
728x90

< 구현할 화면 >

- profile에 user명을 함께 보여준다.

- userName을 update할 수 있다.

 

< Navigation.js >

- 네비게이션의 profile을 보여주는 link에 userName을 함께 표시한다.

import React from 'react';
import {Link} from "react-router-dom";

const Navigation = ({userInfo}) =>{
    const userName=userInfo[Object.keys(userInfo)[0]].displayName;
    return(
        <nav>
        <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/profile">{userName}'s profile</Link></li>
        </ul>
        </nav>
    );
};

export default Navigation;

 

<Router.js>

- Profile component를 routing할 때 Home component와 동일하게 userInfo를 함께 넘겨준다.

import React from 'react';
import {Redirect, HashRouter as Router, Route, Switch} from "react-router-dom"
import Auth from "../routes/Auth";
import Home from "../routes/Home";
import Profile from "../routes/Profile";
import Navigation from "./Navigation"

const AppRouter = (isLoggedIn, {userInfo})=>{
    const flag=isLoggedIn[Object.keys(isLoggedIn)[0]];

    return( 
        <Router>
            {flag&&<Navigation userInfo={isLoggedIn.userInfo}/>}
            <Switch>
                {flag? (
                    <> 
                        <Route exact path="/"><Home userInfo={isLoggedIn.userInfo}/></Route>
                        <Route exact path="/profile"><Profile userInfo={isLoggedIn.userInfo}/></Route>
                        <Redirect from="*" to="/" />
                    </>
                ) : (
                    <>
                        <Route exact path="/"><Auth /></Route>
                        <Redirect from="*" to="/" />
                    </>
                )}
            </Switch>
        </Router>
    );
}
export default AppRouter;

<Profile.js>

import { authService, dbService } from 'fBase';
import React,{useEffect,useState} from 'react';
import { useHistory } from 'react-router-dom';
import { collection, getDocs, query, where, orderBy } from "@firebase/firestore";
import { updateProfile } from "@firebase/auth";

export default ({userInfo})=>{
    const userId=userInfo[Object.keys(userInfo)[0]].uid;
    const userName=userInfo[Object.keys(userInfo)[0]].displayName;
    const [newDisplayName, setNewDisplayName] = useState(userName);
    
    const history=useHistory();
    const onLogOutClick = () => {
        authService.signOut();
        history.push("/");
    };

    const onChange = (event) =>{
        const{
            target : {value},
        } = event;
        setNewDisplayName(value);
    }

    const getMyTweets = async () => {
        const q = query( 
            collection(dbService, "tweets"),
            where("creatorId", "==", userId)
            , orderBy('createdAt', 'desc')
        );
        
        const querySnapshot = await getDocs(q);
        
        querySnapshot.forEach((doc) => { 
            console.log(doc.id, " => ", doc.data());
        });
    };

    useEffect(() => {
        getMyTweets();
    }, [])

    const onSubmit=async(event)=>{
        event.preventDefault();
        if (userName !== newDisplayName) {
            await updateProfile(userInfo[Object.keys(userInfo)[0]], { displayName: newDisplayName });
        }
    };

    return(
        <>
            <form onSubmit={onSubmit}>
                <input type="text" placeholder="Display name" 
                    onChange={onChange} value={newDisplayName}/>
                <input type="submit" value="Update Profile"/>
            </form>
            <button onClick={onLogOutClick}>Log Out</button>
        </>
    );
};

 

1.

import { authService, dbService } from 'fBase';
import React,{useEffect,useState} from 'react';
import { useHistory } from 'react-router-dom';
import { collection, getDocs, query, where, orderBy } from "@firebase/firestore";
import { updateProfile } from "@firebase/auth";

export default ({userInfo})=>{
    const userId=userInfo[Object.keys(userInfo)[0]].uid;
    const userName=userInfo[Object.keys(userInfo)[0]].displayName;
    const [newDisplayName, setNewDisplayName] = useState(userName);
    
    const history=useHistory();
    
    const onLogOutClick = () => {
        authService.signOut();
        history.push("/");
    };

[newDisplayName, setNewDisplayName] 

  : user가 닉네임을 변경할 때 사용되는 state로, sns 로그인 시 전달된 displayName으로 초기화 된다.

onLogOutClick   : authService로 부터 logout 하고 "/"(home)으로 이동한다.

     useHistory hook을 사용하면 onClick event의 발생 시 경로가 괄호 안의 경로로 변경된다. ("/")

 

 

2. getMyTweets 함수

    const getMyTweets = async () => {
        const q = query( 
            collection(dbService, "tweets"),
            where("creatorId", "==", userId)
            , orderBy('createdAt', 'desc')
        );
        
        const querySnapshot = await getDocs(q);
        
        querySnapshot.forEach((doc) => { 
            console.log(doc.id, " => ", doc.data());
        });
    };

    useEffect(() => {
        getMyTweets();
    }, [])

const q = query(...);  : firebase의 collection인 dbService에서 tweets를 변수 q에 가져온다.

    조건 : tweet의 creatorId와 현재 로그인 중인 userId가 동일한 tweet

-  const querySnapshot = await getDocs(q);  : q에 저장된 documents들을 가져와 querySnapshot 변수에 저장

-  querySnapshot.forEach(...);  : querySnapshot을 순회하며 현재 login 중인 user가 작성했던 tweet들을 가져온다.

useEffect(...)  : Profile component가 mount 되었을 때 getMyTweets 함수를 실행한다.

 

 

3. onChange 함수

    const onChange = (event) =>{
        const{
            target : {value},
        } = event;
        setNewDisplayName(value);
    }

- user가 displayName을 변경했을 때 실행되는 event handler

 

 

4. onSubmit 함수

    const onSubmit=async(event)=>{
        event.preventDefault();
        if (userName !== newDisplayName) {
            await updateProfile(userInfo[Object.keys(userInfo)[0]], { displayName: newDisplayName });
        }
    };

- user가 displayName 변경 후 submit 했을 때 실행되는 event handler

 

 

 

728x90