로그인시 사용자 컬렉션에서 사용자 데이터 가져 오기

Nov 21 2020

현재 클라이언트 측에서 firebase가 초기화 된 애플리케이션에서 작업 중입니다. 사용자가 firebase를 통해 로그인 할 때 firestore에서 사용자 데이터를 가져오고 싶습니다. 현재 onAuthStateChanged리스너 내에서 수행하고 있으며 사용자를 성공적으로 가져옵니다. 이것이 사용자 데이터를 가져 오는 가장 좋은 방법인지 궁금합니다. 내 코드는 다음과 같습니다.

  const [currentUser, setCurrentUser] = useState(null)
  const [authState, setAuthState] = useState(false)

  useEffect(() => {
    console.log('state unknown')
    setAuthState(false)
    auth().onAuthStateChanged(user => {
      if (!user) {
        return
      }
      const sourceRef = firestore()
        .collection('users')
        .where('userId', '==', user.uid)
      sourceRef
        .get()
        .then(snapshot => {
          if (snapshot.empty) {
            console.log('user not found')
          } else {
            let data = {}
            snapshot.forEach(item => (data = item.data()))
            console.log(data)
            setCurrentUser(data)
            setAuthState(true)
          }
        })
        .catch(error => console.log(error.code))
    })
  }, [])

  return (
    <AppContext.Provider value={{ currentUser, authState }}>
      {children}
    </AppContext.Provider>
  )
}

내 주요 관심사는 응용 프로그램을 새로 고칠 때마다 사용자의 데이터를 가져 오는 것입니다. 문제에 대한 제안이나 모범 사례는 대단히 감사하겠습니다.

답변

2 LouisCoulet Nov 21 2020 at 17:55

컨텍스트 API 및 인증 관찰자를 사용하는 IMHO 접근 방식은 사소한 문제만으로 이미 훌륭합니다.

  • Awran5에서 언급 한대로 옵저버 구독을 취소해야합니다.
  • 사용자 데이터를 한 번만 가져 오는 대신 관찰 할 수 있습니다.
  • 가독성과 성능을 위해 컨텍스트를 분리 할 수 ​​있습니다.
  • 소유자의 ID로 컬렉션 사용자에서 문서를 만들 수 있으므로 collection("users").doc(authUser.uid)쿼리를 수행하는 대신 직접 액세스 할 수 있습니다.

다음은 귀하의 예를 수정하는 방법입니다. 최선의 방법인지 확실하지 않은 경우 다른 의견을 기다리고 있습니다.

const AuthContext = React.createContext();

function AuthProvider({ children }) {
    const [authUser, setAuthUser] = React.useState(undefined);

    React.useEffect(() => {
        return firebase.auth().onAuthStateChanged(user => setAuthUser(user));
    }, []);

    return <AuthContext.Provider value={authUser}>{children}</AuthContext.Provider>;
}
const UserDataContext = React.createContext();

function UserDataProvider({ children }) {
    const [userData, setUserData] = React.useState(null);
    const authUser = React.useContext(AuthContext);

    React.useEffect(() => {
        if (!authUser) return;
        const query = firebase.firestore().collection("/users").where("userId", "==", authUser.uid);
        return query.onSnapshot(snapshot => setUserData(snapshot.empty ? null : snapshot.docs[0].data()));
    }, [authUser]);

    return <UserDataContext.Provider value={userData}>{children}</UserDataContext.Provider>;
}
export default function App() {
    return (
        <AuthProvider>
            <UserDataProvider>
                {/* ... other components */}
                <MyComponent />
            </UserDataProvider>
        </AuthProvider>
    );
}
function MyComponent() {
    const authUser = React.useContext(AuthContext);
    const userData = React.useContext(UserDataContext);
    if (authUser === undefined) return <div>loading user authentication...</div>;
    if (authUser === null) return <div>logged out</div>;
    return <div>User data: {JSON.stringify(userData)}</div>;
}

구성 요소는 인증 상태 변경 또는 사용자 데이터 변경시 여전히 다시 렌더링되지만 필요한 경우에만 해당됩니다.