Firebase 身份验证 Redux useSelector

问题描述 投票:0回答:1

我想在登录成功时重定向到下一个屏幕,但是我在 redux 实现方面遇到了问题。我能够完成登录/注册并获取当前用户,但在应该包含路由的文件中,我没有获取用户信息。当我成功登录时,屏幕保持不变。我的仓库:https://github.com/carlos-ediaz/tap.git

我的index.js文件:

[...]
import { **userAuthStateListener **} from "../../redux/actions/auth";

const Stack = createNativeStackNavigator();

export default function Route() {
    const currentUserObj = useSelector((state) => state.auth);

    const dispatch = useDispatch();

    useEffect(() => {
      dispatch(**userAuthStateListener**());
    }, []);

    if (!currentUserObj?.loaded) {
      return (
        <View>
          <Text>No loaded</Text>
        </View>
      );
    }
    return (
      <NavigationContainer>
        <Stack.Navigator>
          {currentUserObj.currentUser ? (
            <Stack.Screen name="home" component={HomeScreen} />
          ) : (
            <Stack.Screen name="auth" component={AuthScreen}/>
          )}
        </Stack.Navigator>
      </NavigationContainer>
    );
}

My redux/actions file: 

[..Other imports...]
import { USER_STATE_CHANGE } from "../constants";

const auth = getAuth(fdb);
export const **userAuthStateListener**= () => (dispatch) => {
    onAuthStateChanged(auth, (user) => {
        if (user) {
            dispatch(**getCurrentUserInfo**());
        } else {
            dispatch({ type: USER_STATE_CHANGE, currentUser: null, loaded: true });
        }
    });
};

export const **getCurrentUserInfo **= () => (dispatch) => {
  const db = getFirestore(fdb);
  console.log("id", auth.currentUser.uid);
  const user = onSnapshot(doc(db, "users", auth.currentUser.uid), (doc) => {
    if (doc.exists) {
      return dispatch({
        type: USER_STATE_CHANGE,
        currentUser: doc.data(),
        loaded: true,
      });
    }
  });
};

export const login = (email, password) => (dispatch) =>
  new Promise((resolve, reject) => {
    signInWithEmailAndPassword(auth, email, password)
      .then(() => {
        resolve();
      })
      .catch((error) => {
        reject(error);
      });
  });

export const register = (email, password) => (dispatch) =>
    new Promise((resolve, reject) => {
      createUserWithEmailAndPassword(auth, email, password)
        .then(() => {
          resolve();
        })
        .catch((error) => {
          reject(error);
        });
});

我已经放了很多console.log,但是函数中有一些东西,因为useEffect只在第一次调用,如果我放...},[currentUserObj]);一直调用该函数但不更新用户信息。

我完成了。不知道该怎么办。真的卡住了

firebase react-native react-redux redux-thunk useselector
1个回答
0
投票

您似乎没有完全正确使用 Firebase 处理程序和 Redux。

onAuthStateChanged
只需调用一次,并传递适当的回调来处理身份验证更改。在
onAuthStateChanged
挂钩中实例化对
useEffect
的调用,并返回清理函数以取消订阅侦听器。

示例:

const auth = getAuth(fdb);

export default function Route() {
  const dispatch = useDispatch();

  const currentUserObj = useSelector((state) => state.auth);

  // Mounting effect to instantiate the auth listener
  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        dispatch(getCurrentUserInfo());
      } else {
        dispatch({
          type: USER_STATE_CHANGE,
          currentUser: null,
        });
      }
    });

    // Unsubscribe when component unmounts
    return unsubscribe;
  }, []);

  if (!currentUserObj?.loaded) {
    return (
      <View>
        <Text>No loaded</Text>
      </View>
    );
  }

  return (
    <NavigationContainer>
      <Stack.Navigator>
        {currentUserObj.currentUser ? (
          <Stack.Screen name="home" component={HomeScreen} />
        ) : (
          <Stack.Screen name="auth" component={AuthScreen}/>
        )}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

同样,

getCurrentUserInfo
动作只需要触发一次获取当前用户的信息。
onSnapshot
实例化一个侦听器,但您可能不想这样做,特别是因为您不清理它们,例如没有逻辑可以取消订阅更改。您可以使用 getDoc 来获取一次数据。

更新示例:

export const getCurrentUserInfo = () => async (dispatch) => {
  const db = getFirestore(fdb);
  const docRef = doc(db, "users", auth.currentUser.uid);
  const doc = await getDoc(docRef);

  return dispatch({
    type: USER_STATE_CHANGE,
    currentUser: doc.exists ? doc.data() : null,
  });
};

在处理分派的动作时,处理reducer中的“isLoading”和“loaded”状态。

© www.soinside.com 2019 - 2024. All rights reserved.