Reputation: 3368
I have a parent component index.js
render() {
const { firstName, token } = this.props.user;
if (token && firstName) {
return (
<View style={{ flex: 1 }}>
<HomeRoot />
</View>
);
}
console.log('=== ELSE');
return (
<View style={{ flex: 1 }}>
<SplashScreen />
</View>
);
}
}
And a SplashScreen that shows while the user is not logged in:
// Methods imports.
import React from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { Asset, AppLoading, Font, DangerZone } from 'expo';
import FadeInView from '../animations/FadeInView';
// Redux actions
import { signinUser } from '../../store/actions/actions';
const { Lottie } = DangerZone;
const styles = StyleSheet.create({
wrapper: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
// ...
});
function cacheImages(images) {
return images.map(image => {
if (typeof image === 'string') {
return Image.prefetch(image);
}
return Asset.fromModule(image).downloadAsync();
});
}
function cacheFonts(fonts) {
return fonts.map(font => Font.loadAsync(font));
}
class SplashScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
isReady: false
};
this.bgAnim = null;
}
setBgAnim(anim) {
// if (anim === null) {
// return;
// }
this.bgAnim = anim;
this.bgAnim.play();
}
async loadAssetsAsync() {
const imageAssets = cacheImages([
// ...
]);
const fontAssets = cacheFonts([{
'cabin-bold': CabinBold,
'league-spartan-bold': LeagueSpartanBold
}]);
await Promise.all([...imageAssets, ...fontAssets]);
}
render() {
if (!this.state.isReady) {
return (
<AppLoading
startAsync={this.loadAssetsAsync}
onFinish={() => this.setState({ isReady: true })}
/>
);
}
return (
<View style={styles.wrapper}>
<Lottie
ref={c => this.setBgAnim(c)}
resizeMode="cover"
style={{
position: 'absolute',
zIndex: 1,
left: 0,
top: 0,
width: '100%',
height: '100%',
}}
source={require('../../../assets/SPLASH_03.json')} // eslint-disable-line
/>
</View>
);t
}
}
export default connect(
null,
{ signinUser }
)(SplashScreen);
The signinUser
calls facebookAuth and then store the fetched user profile and token in one unique dispatch
.
At this point the index.js
token && firstName
are true and the SplashScreen
component should let his place to HomeRoot
.
However it crashes on SplashScreen
render method: ref={c => this.setBgAnim(c)}
. If we remove this line, or check to discard c
when c
is null
everything works as expected.
Why is c
null at this stage in ref={c => this.setBgAnim(c)}
?
How should I handle this problem in a better way than checking for null?
Upvotes: 2
Views: 458
Reputation: 36199
React will call the ref callback with the DOM element when the component mounts, and call it with null when it unmounts. ref callbacks are invoked before componentDidMount or componentDidUpdate lifecycle hooks.
Knowing that at some points ref passed to callback will be a null, just do a check:
setBgAnim(anim) {
this.bgAnim = anim;
if(anim) {
this.bgAnim.play();
}
}
I don't think there is something wrong with such approach.
Upvotes: 4