我想在登录成功时重定向到下一个屏幕,但是我在 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 处理程序和 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”状态。