在初始加载期间对本地保护已验证的屏幕作出反应



我制作了一个使用firebase电子邮件/通行证身份验证的应用程序,并使用redux-toolkit管理状态,一切都很好,除了糟糕的用户体验,也就是说,当应用程序打开时,需要一秒钟来确定用户是否登录,因此,我在redux中有一个加载状态,也很好,但在初始加载期间,我可以先看到我的LoginScreen显示,然后在一两秒钟后,如果用户以前登录过,它会显示我的HomeScreen,所以我需要提供一个LoadingScreen来隐藏这种转换,并且在每次加载操作完成时只显示一个特定的屏幕。

我尝试添加一个本地状态,并在onAuthStateChange函数内完成所有操作时将其设置为false,但它不起作用。

我的问题视频:https://drive.google.com/file/d/1a8Bu1bTqAANsWKDs0e5bjqVdZJWJRcMv/view?usp=sharing

请查看录音(上面的链接),以便您正确理解情况

下面是我的代码、入口文件和redux工具包状态文件:

条目文件:

const EntryPoint = () => {
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user);
const authloading = useSelector(state => state.auth.loading);
useEffect(() => {
onAuthStateChanged(auth, result => {
if (result) {
const path = doc(db, 'users', result.uid);
getDoc(path)
.then(result => {
if (result.exists()) {
const data = result.data();
dispatch(
login({
displayName: data['displayName'],
email: data['email'],
photoURL: data['photoURL'],
phone: data['phone'],
}),
);
}
})
.catch(error => console.log('sign in error: ', error));
} else {
dispatch(logout());
}
dispatch(loading(false));
});
}, []);
if (authloading) return <Loader />;
return (
<Stack.Navigator>
{user ? <Stack.Screen name="Home" component={Home} /> : <Stack.Screen name="SignIn" component={SignIn} />}
</Stack.Navigator>
);
};

Redux状态:

import { createSlice } from "@reduxjs/toolkit";
const initialState = {
user: null,
loading: true,
}
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
login: (state, action) => {
state.user = action.payload;
},
logout: (state) => {
state.user = null;
},
loading: (state, action) => {
state.loading = action.payload;
},
}
});

我认为之所以会发生这种情况,是因为您在设置user之前设置了loading = false,这一点非常清楚,因为user将在getDoc调用之后设置(这会产生1秒或2秒的"坏用户体验")。

Reduxdispatch返回一个Promise,因此您可以在设置用户后使用该Promise将loading设置为false:

const EntryPoint = () => {
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user);
const authloading = useSelector(state => state.auth.loading);
useEffect(() => {
onAuthStateChanged(auth, result => {
if (result) {
const path = doc(db, 'users', result.uid);
getDoc(path)
.then(result => {
if (result.exists()) {
const data = result.data();
dispatch(
login({
displayName: data['displayName'],
email: data['email'],
photoURL: data['photoURL'],
phone: data['phone'],
}),
)
.then(result => { dispatch(loading(false)); }); //<-- after user is setted, remove loading
}
else dispatch(loading(false)); //<-- if result does not exixsts, remove loading
})
.catch(error => {
dispatch(loading(false)); //<-- in case of error, remove loading
console.log('sign in error: ', error);
});
} else {
dispatch(logout())
.then(result => { dispatch(loading(false)); }); //<-- after logout, remove loading
}
});
}, []);
if (authloading) return <Loader />;
return (
<Stack.Navigator>
{user ? <Stack.Screen name="Home" component={Home} /> : <Stack.Screen name="SignIn" component={SignIn} />}
</Stack.Navigator>
);
};

通过这种方式,您可以100%确定只有在设置了用户之后,加载才会设置为false(避免糟糕的用户体验)。

相关内容

  • 没有找到相关文章

最新更新