본문 바로가기
Web Service/React

[트위터 클론 코딩] #8. Edit

by junnykim 2022. 5. 6.

~5.2까지의 강의

 

이번 강의에서는 프로필 설정하는 것을 위주로 진행하고자 한다. 

프로필에서 로그아웃과 프로필 업데이트, 내가 쓴 글확인을 하고자 한다.

 

많은게 있지만 로그아웃은 끝났고, 이제 프로필을 업데이트 하는 것을 해보자.

여기에서는 세팅을 해보도록 하자.

데이터베이스의 스냅샷을 가지고 오는 것이다.

EditProfile.js를 삭제하고, Profile.js에 모든 것을 넣도록 하자.

 

Profile.js

import React,{useEffect} from "react";
import { authService, dbService } from "fbase";
import { useHistory } from "react-router-dom";

export default ({userObj}) => {
    const history = useHistory();
    const onLogOutClick = () => {
      authService.signOut();
      history.push("/");
    };
    const getMyNweets = async () => {
      const nweets = await dbService
        .collection("nweets")
        .where("creatorId", "==", userObj.uid)
        .orderBy("createdAt")
        .get();
      console.log(nweets.docs.map((doc) => doc.data()));
    };
  
    useEffect(() => {
      getMyNweets();
    }, []);
    return (
      <>
        <button onClick={onLogOutClick}>Log Out</button>
      </>
    );
  };

로그아웃에서 useEffect를 할 것이다. 우리가 할 것은

Nweets를 얻는 함수를 만드는 것이다.

이것은 getMyNweets이고, 당연히 async 여야 한다.

dbService인데 중요한 건 이 프로필 화면은 누군지 모른다.

우리는 우리가 모르는 nweet를 만들 수 없다.

 

<Route exact path="/profile">             
  <Profile userObj={userObj} />           
</Route>

따라서, router.js에서 우리에게 userobj를 주고 있다. 프로필도 userobj를 prop으로 받는다. 

누가 화면을 보고있는지 알 수 있다. 즉, 우리가 어떤 유저의 nweets를 불러와야 할 지 아는 것이다. 

 

다시 Profile.js로 돌아가서, getMyNweets를 보자. 기본적으로 where는 필터링 하는 것을 알려준다.

즉, nweets를 얻는 것이다.

orderby하면 정렬하는 것이다.

 

이렇게 하고 실행하면, 파이어스토어는 sql 기반이라 오류가 난다.

쿼리에는 index가 뜬다고 뜬다. pre-made 쿼리를 사용할것으로 데이터베이스에 말해주어야 한다.

 

선생님은 링크가 뜨지만,,, 나는,, (오타 때문이었던 걸로)

 

선생님 링크타면 이렇게 뜬다.

링크가 안 떠서 보면서 직접 만들었다. 

순서는 asc, desc로 설정할 수 있다. 

 

아무튼 이런식으로 하면 된다~!


이제는 myProflie이름을 그 사람의 이름으로 바꾸자. 즉 디스플레이 이름으로

 

 {isLoggedIn && <Navigation userObj={userObj} />}

Router.js가면 Navigation이 있는데 userObj를 보내서, userObj의 디스플레이 이름을 가지게 하도록 하자. 

즉, 어디에서든지 최신 데이터를 사용하도록 하자.

 

Profile.js

import React,{useState} from "react";
import { authService} from "fbase";
import { useHistory } from "react-router-dom";

export default ({userObj}) => {
    const history = useHistory();
    const [newDisplayName, setNewDisplayName] = useState(userObj.displayName);
    const onLogOutClick = () => {
      authService.signOut();
      history.push("/");
    };
    const onChange = (event) => {
      const {
        target: { value },
      } = event;
      setNewDisplayName(value);
    };
    const onSubmit = async (event) => {
      event.preventDefault();
      if (userObj.displayName !== newDisplayName) {
        await userObj.updateProfile({
          displayName: newDisplayName,//여기에 photourl넣어도 됨
        });
      }
    };
  
    return (
      <>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          type="text"
          placeholder="Display name"
          value={newDisplayName}
        />
        <input type="submit" value="Update Profile" />
      </form>
        <button onClick={onLogOutClick}>Log Out</button>
      </>
    );
  };

프로필로가서 form을 만들자. 안에 다양한 것들이 있다.

value는 새로운 newDisplayName이다. 즉, 이제 이름을 볼 수 있고, 그 후에는 업데이트 할 것이다.

submit에서 아무것도 변경하지 않은 상태에서 버튼을 누르면 업데이트 한다.

 

updateprofile을 사용할 것이다.

바뀌긴 하는데 새로고침을 해야 바뀐다.

 


이제 업데이트하면, 바로 바뀌도록 해보자.

userObj를 여기저기 사용하는 이유는 uid를 사용하기 때문이다. 

우리가 새로운 정보를 적용하거나 상태의 변화가 있을 떄, useObj를 사용하면, 지정된 userObj의 처음에 가도록 한다. 

 

App.js

import React, { useState, useEffect } from "react";
import AppRouter from "components/Router";
import { authService } from "fbase";


function App() {
  const [init, setInit] = useState(false);
  const [userObj, setUserObj] = useState(null);
  useEffect(() => {
    authService.onAuthStateChanged((user) => {
      if (user) {
        setUserObj({
          displayName: user.displayName,
          uid: user.uid,
          updateProfile: (args) => user.updateProfile(args),
        });
      }
      setInit(true);
    });
  }, []);
  const refreshUser = () => {
    const user = authService.currentUser;
    setUserObj({
      displayName: user.displayName,
      uid: user.uid,
      updateProfile: (args) => user.updateProfile(args),
    });
  };
  return (
    <>
      {init ? (
        <AppRouter
        refreshUser={refreshUser}
        isLoggedIn={Boolean(userObj)}
        userObj={userObj}
      />
      ) : (
        "Initializing..."
      )}
    </>
  );
}

export default App;

refreshUser는 user를 새로고침하는 함수이다.

 

user를 새로고침하도록 해야하는데, 네비게이션은 파이어베이스와 연동되어 있지 않다.

따라서, refreshUser를 Router로 전달 한 후에, Profile로 가지고 온다.

 

Router.js

더보기
import React from "react";
import { 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 "components/Navigation";


const AppRouter = ({ refreshUser, isLoggedIn, userObj }) => {
  return (
    <Router>
      {isLoggedIn && <Navigation userObj={userObj} />}
      <Switch>
        {isLoggedIn ? (
          <>
            <Route exact path="/">
              <Home userObj={userObj} />
            </Route>
            <Route exact path="/profile">
              <Profile userObj={userObj} refreshUser={refreshUser} />
            </Route>
          </>
        ) : (
          <>
            <Route exact path="/">
              <Auth />
            </Route>
          </>
          
        )}
      </Switch>
    </Router>
  );
};
export default AppRouter;

 

Profile.js

더보기
import React,{useState} from "react";
import { authService} from "fbase";
import { useHistory } from "react-router-dom";

export default ({ refreshUser, userObj }) => {
    const history = useHistory();
    const [newDisplayName, setNewDisplayName] = useState(userObj.displayName);
    const onLogOutClick = () => {
      authService.signOut();
      history.push("/");
    };
    const onChange = (event) => {
      const {
        target: { value },
      } = event;
      setNewDisplayName(value);
    };
    const onSubmit = async (event) => {
      event.preventDefault();
      if (userObj.displayName !== newDisplayName) {
        await userObj.updateProfile({
          displayName: newDisplayName,//여기에 photourl넣어도 됨
        });
        refreshUser();
      }
    };
  
    return (
      <>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          type="text"
          placeholder="Display name"
          value={newDisplayName}
        />
        <input type="submit" value="Update Profile" />
      </form>
        <button onClick={onLogOutClick}>Log Out</button>
      </>
    );
  };

댓글