我正在尝试使用Redux创建具有用户登录功能的基本应用程序来管理用户详细信息。我已经在下面链接了我的屏幕的GIF,并且如您所见,在加载组件和用户详细信息渲染之间存在延迟。还记录了我的组件配置文件代码。
Name of user delay when loading
import React, {Component} from 'react';
import {View, StyleSheet, Text, TouchableOpacity} from 'react-native';
import {connect} from 'react-redux';
import {fetchProfile} from '../../actions/ProfileActions';
import {logoutUser} from '../../actions/AuthActions';
class Profile extends Component {
state = {
firstName: '',
lastName: '',
email: '',
goals: '',
};
componentDidMount() {
this.props.fetchProfile();
}
componentDidUpdate(prevProps) {
if (prevProps !== this.props) {
this.setState({
firstName: this.props.profile.firstName,
lastName: this.props.profile.lastName,
email: this.props.profile.email,
goals: this.props.profile.goals,
});
}
}
onPressLogout = () => {
this.props.logoutUser();
};
render() {
return (
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.header}>
Profile of {this.state.firstName} {this.state.lastName}
</Text>
</View>
<View style={styles.textContainer}>
<TouchableOpacity
style={styles.buttonContainer}
onPress={this.onPressLogout.bind(this)}>
<Text style={styles.buttonText}>Logout</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const mapStateToProps = (state) => ({
profile: state.profile.profile,
});
export default connect(mapStateToProps, {fetchProfile, logoutUser})(Profile);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F9F9F9',
},
headerContainer: {
marginTop: 75,
marginLeft: 20,
},
header: {
fontSize: 34,
fontWeight: '700',
color: '#000000',
},
textContainer: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
marginBottom: 30,
},
buttonContainer: {
backgroundColor: '#34495E',
alignItems: 'center',
padding: 12,
width: 350,
borderRadius: 15,
},
buttonText: {
color: 'white',
fontWeight: 'bold',
fontSize: 19,
},
});
编辑:我忘了解释fetchProfile()
的作用。它连接到Firebase数据库以检索用户的详细信息。下面的代码:
import {PROFILE_FETCH} from './types';
import firebase from 'firebase';
export const fetchProfile = () => {
const {currentUser} = firebase.auth();
return (dispatch) => {
firebase
.database()
.ref(`/users/${currentUser.uid}/profile`)
.on('value', (snapshot) => {
dispatch({
type: PROFILE_FETCH,
payload: snapshot.val(),
});
});
};
};
此外,我在应用程序中有3个不同的屏幕,所有这些屏幕都可能会利用用户的详细信息。我敢肯定,必须有一种更有效的方法,只需一次fetchProfile()
,然后以某种方式将详细信息传递给每个组件...
我该怎么办,以便用户登录时,其详细信息已经加载到组件中,因此没有延迟?预先感谢!
答案 0 :(得分:0)
解决这个问题的一种方法是有条件地渲染skeleton(如果它仍在加载),然后在完成后实际渲染细节。 我不确定这是否正是您要寻找的解决方案(您可能已经知道这是一个选择),但这也许有帮助吗?
答案 1 :(得分:0)
根据您提供的内容,肯定会有延迟。我将在这里说明发生了什么。
在个人资料上呈现详细信息后,您正在从Firebase请求数据。发生这种情况是因为您要在componentDidMount方法中请求数据。首次调用此方法时,Render方法完全完成了组件的渲染。因此,我建议您使用两种方法来消除这种情况。
fetchProfile
操作请求这些数据,一旦完全获取了这些数据,就可以使用Navigation.navigate('Profile')
导航到“个人资料”屏幕,而不是直接导航到该屏幕认证成功。在那段时间内,因为您已经获取了数据,所以不会有任何问题。 此外,您还可以使用firebasepersist选项在本地存储这些数据。因此,即使没有互联网连接,firebase仍会迅速提供您的个人资料信息。
编辑
更具体的答案,带有一些随机的类和函数名称。这只是一个例子。
让我们说onLogin函数处理您的身份验证类中的所有登录要求。
onLogin = () => {
/** Do the validation and let's assume validation is success */
/** Now you are not directly navigating to your Profile page like you did in the GIF. I assume that's what you did because you have not added more code samples to fully understand what you have done.*/
/** So now you are calling the fetchProfile action through props and retrieve your details. */
this.props.fetchProfile(this.props.navigation);
};
现在让我们修改您的fetchDetails操作。
export const fetchProfile = (navigation) => {
const {currentUser} = firebase.auth();
return (dispatch) => {
firebase
.database()
.ref(`/users/${currentUser.uid}/profile`)
.on('value', (snapshot) => {
dispatch({
type: PROFILE_FETCH,
payload: snapshot.val(),
});
navigation.navigate('Profile')
});
};
};
注意:这不是处理导航的最佳方法,而是使用全局导航服务直接访问顶级导航器。您可以在React Navigation Documentation中进一步了解。但是,在此示例中,我们现在就使用它。
如您所见,当用户登录成功时,现在您不需要在渲染“个人档案”页面后请求数据,而是在导航到该页面之前就请求数据。因此,这可以确保配置文件页面仅加载相关数据,并且不会像GIF中那样出现延迟。
答案 2 :(得分:0)
您必须使用Firebase创建一个侦听器。
做这样的事情:
减速器动作:
// Action Creators
export function onAuthChanged(fb) {
return async (dispatch) => {
fb.auth().onAuthStateChanged((res) => {
dispatch({
type: Types.SET_ATTR,
payload: {
attr: 'user',
value: res,
},
});
});
};
}
从FirebaseProvider componentWillMount函数调用此函数
然后
将FirebaseProvider放在您的App类上;
const App = () => {
return (
<>
<Provider store={store}>
<TranslatorProvider />
<FirebaseProvider />
<ThemeProvider>
<TrackingProvider>
<Routes />
</TrackingProvider>
</ThemeProvider>
</Provider>
</>
);
};
监听器将在登录和注销时将用户保存在您的reducer上