I'm using the react-native-circular-progress component and I'm trying to loop an animation every 30 seconds.
i.e the animation is 30 seconds long and i want it to restart as soon as its done
The component exposes a function named reAnimate which I have put in a setInterval function as soon as the component mounts.
import React from 'react';
import { StyleSheet, Text, View,Dimensions, Easing } from 'react-native';
import { AnimatedCircularProgress } from 'react-native-circular-progress';
const MAX_POINTS = 30;
export default class App extends React.Component {
state = {
isMoving: false,
pointsDelta: 0,
points: 1,
};
componentDidMount(){
setInterval(
() => this.circularProgress.reAnimate(0,100, 30000,Easing.linear),
30000
);
}
render() {
const { width } = Dimensions.get("window");
const window = width - 120;
const fill = (this.state.points / MAX_POINTS) * 100;
return (
<View style={styles.container} >
<AnimatedCircularProgress
size={window}
width={7}
backgroundWidth={5}
fill={0}
tintColor="#ef9837"
backgroundColor="#3d5875"
ref={(ref) => this.circularProgress = ref}
arcSweepAngle={240}
rotation={240}
lineCap="round"
>
{fill => <Text style={styles.points}>{Math.round((MAX_POINTS * fill) / 100)}</Text>}
</AnimatedCircularProgress>
</View>
);
}
}
const styles = StyleSheet.create({
points: {
textAlign: 'center',
color: '#ef9837',
fontSize: 50,
fontWeight: '100',
},
container: {
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#0d131d',
padding: 50,
},
pointsDelta: {
color: '#4c6479',
fontSize: 50,
fontWeight: '100',
},
pointsDeltaActive: {
color: '#fff',
},
});
This is working... BUT... the animation only starts 30s after the component mounts. How do i get it to loop immediately?
Any help will be greatly appreciated.
Thank you.
The reason is setInterval will not fire immediately it will start after the duration you passed i.e 30 mins, So all you have to do is make a call initially before setting the interval, also don't forget to clear the interval.
Here's how I would it:
componentDidMount(){
this.circularProgress.animate(100, 30000,Easing.linear);
this.intervalId = setInterval(
() => this.circularProgress.reAnimate(0,100, 30000,Easing.linear),
30000
);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
Related
I recently started trying to use animation in an app I am trying to make in React Native.
I am not 100% familiar with React Animated, but I believe the animations that I am trying to make are very simple.
I have a screen where I would like some text to slide in from the right, pause a few seconds, slide out to the left, before repeating itself with some other text.
While I did manage to do that, the animation and the text quickly become very buggy (aka no smooth animation, no animation at all after a while, the text will very quickly change randomly, etc...).
I am not sure why this is, I tried switching the useNativeDriver to true to hopefully get a smoother animation, but then I get an error saying I can't use the style property 'left'.
Here is the code:
import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';
function App() {
let [wordsAnim] = useState(new Animated.Value(60)),
runAnimation = () => {
wordsAnim.setValue(60);
Animated.sequence([
Animated.timing(wordsAnim, {
toValue: 0,
duration: 1500,
useNativeDriver: false,
}),
Animated.timing(wordsAnim, {
toValue: -60,
duration: 1500,
delay: 3000,
useNativeDriver: false,
}),
]).start(({ finished }) => {
runAnimation();
updateWord();
});
};
//An array of random words to display
const words = ['First', 'Second', 'Third', 'Fourth'];
//First word displayed is a random word from the array
const [word, changeWord] = useState(
words[Math.floor(Math.random() * words.length)]
);
//Update the word displayed with another random word from the array
const updateWord = () => {
const index = Math.floor(Math.random() * words.length);
changeWord(words[index]);
};
useEffect(() => {
runAnimation();
});
return (
<View style={styles.container}>
<Animated.Text
style={{
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
left: wordsAnim.interpolate({
inputRange: [0, 100],
outputRange: ['0%', '100%'],
}),
}}>
{word}
</Animated.Text>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
You can also find this example here.
I would also take any tips regarding animations or anything else for React Native,
Thanks!!
As pointed out by #David784 , my runAnimation was retriggered after every completed render. It should've only be run on component mounts.
Adding a few callbacks did the trick!
Working code below:
import React, { useState, useCallback, useEffect } from 'react';
import { Text, View, StyleSheet, Animated } from 'react-native';
import Constants from 'expo-constants';
function App() {
let [wordsAnim] = useState(new Animated.Value(60)),
runAnimation = useCallback(() => {
wordsAnim.setValue(60);
Animated.sequence([
Animated.timing(wordsAnim, {
toValue: 0,
duration: 1500,
useNativeDriver: false,
}),
Animated.timing(wordsAnim, {
toValue: -60,
duration: 1500,
delay: 3000,
useNativeDriver: false,
}),
]).start(({ finished }) => {
updateWord();
runAnimation();
});
}, [updateWord, wordsAnim]);
//An array of random words to display
const words = ['First', 'Second', 'Third', 'Fourth'];
//First word displayed is a random word from the array
const [word, changeWord] = useState(
words[Math.floor(Math.random() * words.length)]
);
//Update the word displayed with another random word from the array
const updateWord = useCallback(() => {
const index = Math.floor(Math.random() * words.length);
changeWord(words[index]);
}, [words]);
useEffect(() => {
runAnimation();
}, [runAnimation]);
return (
<View style={styles.container}>
<Animated.Text
style={{
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
left: wordsAnim.interpolate({
inputRange: [0, 100],
outputRange: ['0%', '100%'],
}),
}}>
{word}
</Animated.Text>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
I have this very simple app, where I am trying to implement countdown, Start and Stop functionality seems to be working fine but when I press Stop, the value of seconds is not updating in the view which is desired behaviour but when I observed console log, it it showing the value of sec continuously changing which I guess shows that setInterval is still running and not cleared.
Here is the accompanied code:
import React, { useState, useEffect } from "react";
import {
StyleSheet,
Text,
View,
StatusBar,
TouchableOpacity,
Dimensions,
} from "react-native";
const screen = Dimensions.get("screen");
export default function App() {
const [seconds, setSeconds] = useState(4);
const [start, setStartToggle] = useState(true);
let [fun, setFun] = useState(null);
const getRemaining = () => {
const minute = Math.floor(seconds / 60);
const second = seconds - minute * 60;
return formatTime(minute) + ":" + formatTime(second);
};
const formatTime = (time) => {
return ("0" + time).slice(-2);
};
const startTimer = () => {
setStartToggle(false);
console.log("StartTimer");
let sec = seconds;
setFun(
setInterval(() => {
console.log("akak:", sec);
if (sec <= 0) stopTimer();
setSeconds(sec--);
}, 1000)
);
};
const stopTimer = () => {
setStartToggle(true);
console.log("StopTimer");
clearInterval(fun);
setFun(null);
};
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<Text style={styles.timerText}>{getRemaining(seconds)}</Text>
{start ? (
<TouchableOpacity onPress={startTimer} style={styles.button}>
<Text style={styles.buttonText}>Start</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
onPress={stopTimer}
style={[styles.button, { borderColor: "orange" }]}
>
<Text style={styles.buttonText}>Stop</Text>
</TouchableOpacity>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#07121B",
alignItems: "center",
justifyContent: "center",
},
button: {
borderWidth: 10,
borderColor: "#89aaff",
width: screen.width / 2,
height: screen.width / 2,
borderRadius: screen.width / 2,
justifyContent: "center",
alignItems: "center",
},
buttonText: {
fontSize: 40,
color: "#89aaff",
fontWeight: "bold",
},
timerText: {
fontSize: 90,
color: "#89aaff",
fontWeight: "bold",
marginBottom: 20,
},
});
App Behaviour:
Output being shown even after Stop is hit:
Thanks to Emiel Zuurbier and lissettdm for their answers, my code is working now.
Working code:
// import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect, useRef } from "react";
import {
StyleSheet,
Text,
View,
StatusBar,
TouchableOpacity,
Dimensions,
} from "react-native";
const screen = Dimensions.get("screen");
export default function App() {
const [seconds, setSeconds] = useState(11);
const funRef = useRef(null);
const [start, setStartToggle] = useState(true);
const getRemaining = () => {
const minute = Math.floor(seconds / 60);
const second = seconds - minute * 60;
return formatTime(minute) + ":" + formatTime(second);
};
const formatTime = (time) => {
return ("0" + time).slice(-2);
};
let sec = seconds;
useEffect(() => {
// let timer = null;
if (!start) {
let sec = seconds;
funRef.current = setInterval(() => {
console.log("Seconds remaining:", sec);
if (sec <= 0) {
clearInterval(funRef.current);
setStartToggle(true);
}
setSeconds(sec--);
}, 1000);
} else {
clearInterval(funRef.current);
}
}, [start]);
const startTimer = () => {
setSeconds(sec);
setStartToggle(false);
};
const stopTimer = () => {
setSeconds(sec);
setStartToggle(true);
};
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<Text
style={
seconds ? styles.timerText : [styles.timerText, { color: "red" }]
}
>
{getRemaining(seconds)}
</Text>
{start ? (
<TouchableOpacity onPress={startTimer} style={styles.button}>
<Text style={styles.buttonText}>Start</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
onPress={stopTimer}
style={[styles.button, { borderColor: "orange" }]}
>
<Text style={styles.buttonText}>Stop</Text>
</TouchableOpacity>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#07121B",
alignItems: "center",
justifyContent: "center",
},
button: {
borderWidth: 10,
borderColor: "#89aaff",
width: screen.width / 2,
height: screen.width / 2,
borderRadius: screen.width / 2,
justifyContent: "center",
alignItems: "center",
},
buttonText: {
fontSize: 40,
color: "#89aaff",
fontWeight: "bold",
},
timerText: {
fontSize: 90,
color: "#89aaff",
fontWeight: "bold",
marginBottom: 20,
},
});
Currently you use the useState hook to store the interval reference. At every re-render of the App component the fun state is reset, but will not be the exact same reference to the interval.
Instead use the useRef hook. It can create a reference to the interval which will not change during re-renders. This means that the value in the current property of the reference will always be the exact same one.
To top it off, use the useEffect hook to watch when a running state is set or unset and start and stop the timer based on that state.
import React, { useState, useRef, useEffect } from 'react'
export default function App() {
const [isRunning, setIsRunning] = useState(false);
const funRef = useRef(null);
const startTimer = () => {
if (!isRunning) {
setIsRunning(true);
}
};
const stopTimer = () {
if (isRunning && funRef.current !== null) {
setIsRunning(false);
}
};
useEffect(() => {
if (isRunning) {
funRef.current = setInterval(() => { // Save reference to interval.
// ...
}, 1000);
} else {
clearInterval(funRef.current); // Stop the interval.
}
}, [isRunning]);
// ...
}
Add interval timer inside useEffect block, and run this block every time start changes:
useEffect(()=> {
let timer = null;
if(!start) {
let sec = seconds;
timer = setInterval(() => {
console.log("akak:", sec);
if (sec <= 0) clearInterval(timer);
setSeconds(sec--);
}, 1000);
} else {
clearInterval(timer);
}
}, [start]);
const startTimer = () => {
setStartToggle(false);
};
const stopTimer = () => {
setStartToggle(true);
};
Also, I recommend you to use the exact remaining time. Javascript is a single threaded language, and this interval could be more than one second
EDIT: using the exact time.
useEffect(() => {
let timer = null;
if (!start) {
let sec = seconds;
const startTime = Date.now();
timer = setInterval(() => {
const currentTime = Date.now();
sec = sec - Math.floor((currentTime - startTime) / 1000);
if (sec < 0) {
clearInterval(timer);
setSeconds(0);
} else {
setSeconds(sec);
}
}, 1000);
}
}, [start]);
I'm trying to make a simple Pomodoro timer. I need to make the pause and stop buttons work.
I defined a separate component called 'Timer' and added two buttons: 'Pause' and 'Stop' which obviously have to affect the state of the Timer.
How do I call the stop and pause method of Timer when the respective Buttons are pressed?
I understand that I can do this by simply including the buttons within the Timer class but I want to learn how to achieve something similar in the future and I'd like to keep the counter part of the Timer independent.
Here is the code:
import React from 'react'
import { Text, View, Button, StyleSheet } from 'react-native';
import { Constants } from 'expo';
class Timer extends React.Component{
constructor (props){
super(props)
this.state = {
minutes: props.minutes,
seconds: props.seconds,
count: 0,
}
}
dec = () => {
this.setState(previousState => {
if (previousState.seconds==0){
return {
minutes: previousState.minutes-1,
seconds: 59,
count: previousState.count+1,
}
}
else{
return{
minutes: previousState.minutes,
seconds: previousState.seconds-1,
count: previousState.count+1,
}
}
});
}
componentDidMount (){
setInterval(this.dec,1000);
}
render (){
return(
<View style = {{flexDirection: 'row'}}>
<Text style = {styles.timerCount}> {this.state.minutes}</Text>
<Text style = {styles.timerCount}>:</Text>
<Text style = {styles.timerCount}> {this.state.seconds} </Text>
</View>
)
}
stop (){
console.log('stop')
}
pause (){
console.log('pause')
}
}
export default class App extends React.Component {
stop (){
console.log('stop')
}
render() {
return(
<View style={styles.container}>
<Timer style = {styles.timer} minutes={25} seconds = {0}/>
<View style = {styles.buttonContainer}>
<Button title = 'Pause' style = {styles.timerButton} color = 'white' onPress = {()=>{console.log("call the timer's pause method here")}}/>
<Button title = 'Stop' style = {styles.timerButton} color = 'white' onPress = {()=>{console.log("call the timer's stop method here")}}/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
buttonContainer: {
flexDirection: 'row',
},
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 50,
backgroundColor: '#EC3D40',
},
timer: {
backgroundColor: '#EC3D40',
paddingTop: 50,
},
timerCount: {
fontSize: 48,
color: 'white',
backgroundColor: '#EC3D40',
paddingTop: 10,
paddingBottom: 10,
},
timerButton:{
borderColor: 'white',
backgroundColor: 'transparent',
}
});
Well actually you can do that using ref feature.
You can create a ref and assign it to your timer component. Then you can call this component's methods.
export default class App extends React.Component {
timerRef = React.createRef();
render() {
return(
<View style={styles.container}>
<Timer style = {styles.timer} minutes={25} seconds = {0} ref={this.timerRef}/>
<View style = {styles.buttonContainer}>
<Button title = 'Pause' style = {styles.timerButton} color = 'white' onPress = {()=>{console.log("call the timer's pause method here"); this.timerRef.current.pause();}}/>
<Button title = 'Stop' style = {styles.timerButton} color = 'white' onPress = {()=>{console.log("call the timer's stop method here"); this.timerRef.current.stop();}}/>
</View>
</View>
);
}
}
But this doesn't seem like a react way of doing things.
I've looked through many other threads with this same issue, but none seem to have the solution I'm looking for. I followed a tutorial off of YouTube (Fullstack Development is the channel, and it is how to make a game in 28 minutes). My main code looks like this:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Dimensions,
Animated,
Image,
} from 'react-native';
import Enemy from './app/components/Enemy';
export default class Blox extends Component {
constructor(props){
super(props);
this.state = {
movePlayerVal: new Animated.Value(40),
playerSide:'left',
points: 0,
moveEnemyVal: new Animated.Value(0),
enemyStartposX: 0,
enemySide: 'left',
enemySpeed: 4200,
gameOver: false,
};
}
render() {
return (
<Image source = {require('./app/img/bg.png')} style={styles.container}>
<View style= {{ flex:1, alignItems: 'center', marginTop: 80 }}>
<View style={styles.points}>
<Text style={{ fontWeight: 'bold', fontSize: 40 }}>{this.state.points}</Text>
</View>
</View>
<Animated.Image source={require('./app/img/car.png')}
style = {{
height:100,
width:100,
position:'absolute',
zIndex:1,
bottom: 50,
resizeMode: 'stretch',
transform: [
{ translateX: this.state.movePlayerVal }
]
}}></Animated.Image>
<Enemy enemyImg={require('./app/img/enemy.png')}
enemyStartposX={this.state.enemyStartposX}
moveEnemyVal={this.state.moveEnemyVal} />
<View style={styles.controls}>
<Text style = {styles.left} onPress={ () => this.movePlayer('left') }> {'<'} </Text>
<Text style={styles.right} onPress={ () => this.movePlayer('right') }> {'>'} </Text>
</View>
</Image>
);
}
movePlayer(direction) {
//move player right
if (direction == 'right') {
this.setState({ playerSide: 'right' }); //issue with setState being used as a function (from lines 78-124)
Animated.spring(
this.state.movePlayerVal,
{
toValue: Dimensions.get('window').width = 140,
tension: 120,
}
).start();
} else if (direction == 'left') {
this.setState({ playerSide: 'left' });
Animated.spring(
this.state.movePlayerVal,
{
toValue: 40,
tension: 120,
}
).start();
}
}
componentDidMount() {
this.animateEnemy();
}
animateEnemy() {
this.state.moveEnemyVal.setValue(-100);
var windowH = Dimensions.get('window').height;
//Generate left distance for enemy
var r = Math.floor(Math.random() * 2) * 1;
if (r == 2) {
r = 40;
this.setState({ enemySide: 'left' });
} else {
r = Dimensions.get('window').width = 140;
//Enemy is on the right
this.setState = ({ enemySide: 'right' });
}
this.setState({ enemyStartposX: r }); //issue with this
//Interval to check for collision each 50 ms
var refreshIntervalId;
refreshIntervalId = ( () => {
//Collision logic
//If enemy collides with player and they are on the same side
//and the enemy has not passed the player safely
if (this.state.moveEnemyVal._value > windowH - 280 && this.state.moveEnemyVal._value < windowH -180 && this.state.playerSide == this.state.enemySide) {
clearInterval(refreshIntervalId)
this.setState({ gameOver: true });
this.gameOver();
}
}, 50);
//Increase enemy speed each 20th second
setInterval ( () => {
this.setState({ enemySpeed: this.state.enemySpeed - 50 })
}, 20000);
//Animate the enemy
Animated.timing(
this.state.moveEnemyVal,
{
toValue: Dimensions.get('window').height,
duration: this.state.enemySpeed,
}
).start(event => {
//if no enemy collision is detected, restart enemy animation
if (event.finished && this.state.gameOver == false) {
clearInterval(refreshIntervalId);
this.setState({ points: ++this.state.points });
this.animateEnemy();
}
});
}
gameOver() {
alert('You lost big time!');
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
position: 'relative',
resizeMode: 'cover',
},
points: {
width: 80,
height: 80,
backgroundColor: '#fff',
borderRadius: 100,
alignItems: 'center',
justifyContent: 'center',
},
controls: {
alignItems: 'center',
flexDirection: 'row',
},
right: {
flex: 1,
color: '#fff',
margin: 0,
fontSize: 60,
fontWeight: 'bold',
textAlign: 'left'
},
left: {
flex: 1,
color: '#fff',
fontSize: 60,
fontWeight: 'bold',
textAlign: 'right'
},
});
I also have an enemy class that looks like this:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Animated,
Image,
} from 'react-native';
export default class Enemy extends Component {
render() {
return (
<Animated.Image source={this.props.enemyImg}
style = {{
height:100,
width:100,
position:'absolute',
resizeMode: 'stretch',
left: this.props.enemyStartposX,
transform: [
{ translateY: this.props.moveEnemyVal },
]
}}></Animated.Image>
);
}
}
I'm running this through Expo XDE, and as I was building it, it worked. However, once I started coding the animation, Expo turned red and said I had an error in line 124 (in App.js), that .setState is not a function, it is an object. I commented it out, and it told me I had the same error in line 78 of my App.js file. Can you tell me what .setState is, and how to potentially fix this error? Thanks.
You have a wrong setState call in your animateEnemy function. That's why you got that error message.
animateEnemy() {
...
if (r == 2) {
r = 40;
this.setState({ enemySide: 'left' });
} else {
r = Dimensions.get('window').width = 140;
// Enemy is on the right
// this.setState = ({ enemySide: 'right' }); // This is wrong
this.setState({ enemySide: 'right' });
}
...
}
And it would be much better if you change all of the function with arrow function animateEnemy = () => { ... }. With this way, you don't need to manually bind it in the constructor.
You should bind the movePlayer function to the proper scope in your constructor:
constructor() {
this.movePlayer = this.movePlayer.bind(this);
}
I think your problem is how you handle the method callback. You just bind method movePlayer() and animateEnemy() in constructor like :
constructor(props) {
super(props);
this.state = {
movePlayerVal: new Animated.Value(40),
playerSide:'left',
points: 0,
moveEnemyVal: new Animated.Value(0),
enemyStartposX: 0,
enemySide: 'left',
enemySpeed: 4200,
gameOver: false,
};
// This binding is necessary to make `this` work in the callback
this.movePlayer = this.movePlayer.bind(this);
this.animateEnemy = this.animateEnemy.bind(this);
}
maybe you can learn deeply about how your handle method in ReactNative in this.
i hope my answer can help you..
I'm implementing a Splash Screen using React Native and i'm simply using a StackNavigator to change the route to the Main activity when the animations in Splash Screen are completed. To do this, I'm trying to find a way for triggering the this.props.navigation.navigate('Main') function.
The question is that how i can implement the onComplete function in my animation class?
Here is my animation code:
import React from 'react';
import { Animated, Text, View } from 'react-native';
class FadeInView extends React.Component {
state = {
fadeAnim: new Animated.Value(0), // Initial value for opacity: 0
}
componentDidMount() {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: 1, // Animate to opacity: 1 (opaque)
duration: 1000, // Make it take a while
}
).start(); // Starts the animation
}
render() {
let { fadeAnim } = this.state;
return (
<Animated.View // Special animatable View
style={{
...this.props.style,
opacity: fadeAnim, // Bind opacity to animated value
}}
>
{this.props.children}
</Animated.View>
);
}
}
export default FadeInView
and my SplashScreen:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image
} from 'react-native';
import FadeInView from '../Animations/FadeInAnimation';
import { StackNavigator } from 'react-navigation';
import RanjoorMain from './RanjoorMain';
class SplashScreen extends Component {
render() {
return (
<View style={styles.container}>
<View style={{flex:1}}></View>
<FadeInView style={{width: 230, height: 230, backgroundColor: 'transparent'}}>
<Image style={styles.introLogo}
source={require('../Images/Logo/Ranjoor.png')}
/>
</FadeInView>
<View style={{flex:1}}></View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#3863cc',
},
welcome: {
fontSize: 45,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#242329',
marginBottom: 5,
},
introLogo: {
width: 230,
height: 230
}
});
/* This StackNavigator will change the route to the RanjoorMain.js after a couple of ms */
const GoToRanjoorMain = StackNavigator({
Splash: { screen: Splas },
Main: { screen: RanjoorMain }
})
GoToRanjoorMain.navigationOptions = {
title: 'Ranjoor',
};
export default SplashScreen
You can provide a completion handler to that start method of an animation.
Animated.timing(
this.state.fadeAnim,
{
toValue: 1,
duration: 1000,
}
).start(() => nav.goToSomeScreen());