undefined is not a function (evaluating'_reactNavigation.NavigationActions.reset') - javascript

I want to navigate a splash screen to next screen after certain timeout. Splash screen have an animation, done with the help of Airbnb Lottie for React Native.
The splashscreen code goes as follows:
import React from "react";
import { Animated, Easing } from "react-native";
import LottieView from "lottie-react-native";
import { NavigationActions } from "react-navigation";
export default class SplashScreen extends React.Component {
static navigationOptions = {
header: null
};
constructor() {
super();
this.state = {
progress: new Animated.Value(0),
}
}
componentDidMount() {
setTimeout(() => {
this.navigateToWalkthrough()
}, 3500);
Animated.timing(this.state.progress, {
toValue: 1,
duration: 3000,
easing: Easing.linear,
}).start();
}
navigateToWalkthrough = () => {
const navigateAction = NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Walkthrough" })],
});
this.props.navigation.dispatch(navigateAction);
}
render() {
return(
<LottieView
source={require("../assets/splash/SplashScreenAnimation.json")}
progress={this.state.progress}
/>
);
}
}
After I run the app following errors comes up:
undefined is not a function (evaluating'_reactNavigation.NavigationActions.reset')
The Main.js file looks like as follows:
import React from "react";
import { View, Text } from "react-native";
import { createStackNavigator } from "react-navigation";
import SplashScreen from "./screens/SplashScreen";
import Walkthrough from "./screens/Walkthrough";
const Routes = createStackNavigator({
Home: {
screen: SplashScreen
},
Walkthrough: {
screen: Walkthrough
}
});
export default class Main extends React.Component {
render() {
return <Routes />;
}
}
Any help/feedback?

reset action is removed from NavigationActions and there is StackActions specific to StackNavigator in v2 of react-navigation.
StackActions is an object containing methods for generating actions
specific to stack-based navigators. Its methods expand upon the
actions available in NavigationActions.
The following actions are supported:
Reset - Replace current state with a new state
Replace - Replace a route at a given key with another route
Push - Add a route on the top of the stack, and navigate forward to it
Pop - Navigate back to previous routes
PopToTop - Navigate to the top route of the stack, dismissing all other routes

import { StackActions, NavigationActions } from 'react-navigation';
navigateToWalkthrough = () => {
const navigateAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Walkthrough" })],
});
this.props.navigation.dispatch(navigateAction);
}

Related

How to detect application first launch in react native app?

In my scenario, I am having three different screens like Page1, Page2, Page3. Here, if the user last visited page 2 then next time if user open application, instead of showing page1 need to show page2. How to achieve this using a react-native application?
I tried by using async storage but don’t know how to manage multiple pages
AsyncStorage.getItem("alreadyLaunched").then(value => {
if(value == null){
AsyncStorage.setItem('alreadyLaunched', true); // No need to wait for `setItem` to finish, although you might want to handle errors
this.setState({firstLaunch: true});
}
else{
this.setState({firstLaunch: false});
}}) // Add some error handling, also you can simply do this.setState({fistLaunch: value == null})
App.js
import { createAppContainer } from 'react-navigation';
import { createStackNavigator} from 'react-navigation-stack';
import FirstPage from './pages/FirstPage';
import SecondPage from './pages/SecondPage';
import ThirdPage from './pages/ThirdPage';
//import all the screens we are going to switch
const App = createStackNavigator({
//Constant which holds all the screens like index of any book
FirstPage: { screen: FirstPage, header: null},
SecondPage: { screen: SecondPage, headerLeft: null, headerBackTitle: null},
ThirdPage: { screen: ThirdPage},
},
{
initialRouteName: 'FirstPage',
}
);
export default createAppContainer(App);
You should use AsyncStorage to store the current screen, so any time you move from a screen to another you should call
AsyncStorage.setItem('screen', 'nameOfYourScreen')
and in App.js you should call
AsyncStorage.getItem('screen');
and affect it to initialRouteName
PS: getItem() is asynchronous.
Create another page say "Decider.js" and also import createSwitchNavigator from react-navigation. and make it your default page every time app launches. and there we will check where was the user last time and navigate to that page.
Let achieve this as below:
App.js
import { createSwitchNavigator, createAppContainer } from 'react-navigation'; //new import createSwitchNavigator
import { createStackNavigator} from 'react-navigation-stack';
import FirstPage from './pages/FirstPage';
import SecondPage from './pages/SecondPage';
import ThirdPage from './pages/ThirdPage';
import Deccider from './pages/Decider.js'; // New deciding screen
//import all the screens we are going to switch
const App = createStackNavigator({
//Constant which holds all the screens like index of any book
FirstPage: { screen: FirstPage, header: null},
SecondPage: { screen: SecondPage, headerLeft: null, headerBackTitle: null},
ThirdPage: { screen: ThirdPage},
},
{
initialRouteName: 'FirstPage',
}
);
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: Decider,
App: App,
},
{
initialRouteName: 'AuthLoading',
}
));
Now on every app launch first screen called will be Decider.js
Decide.js
import React from 'react';
import {
AsyncStorage,
View,
} from 'react-native';
export default class AuthLoadingScreen extends React.Component {
constructor() {
super();
this._bootstrapAsync();
}
_bootstrapAsync = async () => {
var alreadyLaunchedPage = await
AsyncStorage.getItem('alreadyLaunchedPage');
if (alreadyLaunchedPage) {
this.props.navigation.navigate(alreadyLaunchedPage);
} else {
this.props.navigation.navigate('App');
}
};
render() {
return (
<View style={{ flex: 1 }}>
{/* Any Loading or splash design */}
</View>
);
}
}
**On every page's (FirstPage,SecondPage,ThirdPage) componentDidMount **
...
componentDidMount(){
AsyncStorage.setItem("alreadyLaunchedPage","FirstPage")//if FirstPage
// AsyncStorage.setItem("alreadyLaunchedPage","SecondPage")//if SecondPage
// AsyncStorage.setItem("alreadyLaunchedPage","ThirdPage")//if ThirdPage
}
...
Hope it will solve your problem.
NOTE: Here we have used createSwitchNavigator to prevent going back to Decider.js once you reach any of the FirstPage, SecondPage or ThirdPage.

How to implement Context API in React Native

I just start looking for changing theme globally, and found Context can do that,
but I've a problem to implement the example code to my react native project,
I've tried this code:
//themeContext.js
const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
})
//App.js
import React, { Component } from 'react';
import {InitialScreen} from './routes/routes';
import { ThemeContext } from './Component/themeContext';
export default class App extends Component {
constructor(props) {
super(props);
this.state={
theme:themes.light,
toggleTheme:this.toggleTheme
}
this.toggleTheme=()=>{
this.setState(state=>({
theme:state.theme === themes.dark ? themes.light : themes.dark
}))
}
}
render() {
console.disableYellowBox = true;
return (
<ThemeContext.Provider value={this.state}>
//this is Login.js
<InitialScreen/>
</ThemeContext.Provider>
);
}
}
//Login.js
import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { ThemeContext } from '../Component/themeContext';
export default class Login extends Component {
render() {
return (
<ThemeContext.Consumer>
{({theme, toggleTheme})=>{
<View style={{backgroundColor:theme.background}}>
<Text>{this.state}</Text>
</View>
}}
</ThemeContext.Consumer>
);
}
}
but i have an error Can't find variable: Component, i don't know where should i put import React from 'react'; cause i think I've add Component var in app.js and login.js
any help would be appreciate
Replace next string in the top of your Login.js instead of
import React from 'react';
with
import React, { Component } from 'react';
Another way is to replace
export default class Login extends Component {
}
with
export default class Login extends React.Component {
}
In App.js updated your App component class defintion by replacing Component with React.Component as shown:
export default class App extends React.Component {
/* existing component code */
}
Make the same change in Login.js as well:
export default class Login extends React.Component {
/* existing component code */
}
These changes will cause the Login and App components to extend from the Component class as defined on the React object exported from 'react'.
Your problem in themeContext.js file
you use createContext() but you don't import React so you will get can't find React
it's should be like this
import React from 'react';
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
};
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});
And in Login.js
import React,{Component} from 'react';

undefined is not an object '_this3.props.navigation()' error in react native

running my react app gives error in navigationOptions() but it is working fine in render() function
App.js
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
import AppNavigator from './routs.js'
class App extends Component {
render() {
return (
<AppNavigator />
)
}
}
export default App
routs.js
import React from 'react'
import Home from './home.js'
import Phone from './phone.js'
import PhoneScreen from './phoneScreen.js'
import {createStackNavigator, createAppContainer} from 'react-navigation';
const MainNavigator = createStackNavigator({
home: {screen: Home},
add: {screen: Phone},
userScreen: {screen: PhoneScreen},
});
const AppNavigator = createAppContainer(MainNavigator);
export default AppNavigator;
home.js
import React from 'react'
import { TouchableOpacity, Text, View, TouchableHighlight, StyleSheet, Button } from 'react-native';
import { Actions } from 'react-native-router-flux';
import {AsyncStorage} from 'react-native';
class Home extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
headerTitle: 'Contacts',
headerRight: (
<Button
onPress={() => this.props.navigation.navigate('add')}
title="create new contact"
color="#000000"
size="20"
/>
),
};
}
export default Home;
"undefind is not an object(evaluating '_this3.props.navigation')"
please give solution
From the React Navigation Docs:
The binding of this in navigationOptions is not the HomeScreen
instance, so you can't call setState or any instance methods on it.
This is pretty important because it's extremely common to want the
buttons in your header to interact with the screen that the header
belongs to.
So, as you can see, this is not what you think it is in this case. Here's more from the docs detailing a working example:
class HomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: <LogoTitle />,
headerRight: (
<Button
onPress={navigation.getParam('increaseCount')}
title="+1"
color="#fff"
/>
),
};
};
componentDidMount() {
this.props.navigation.setParams({ increaseCount: this._increaseCount });
}
state = {
count: 0,
};
_increaseCount = () => {
this.setState({ count: this.state.count + 1 });
};
/* later in the render function we display the count */
}
As you can see, changing navigationOptions from an object into a function allows you to grab the navigation reference. From there you can successfully navigate.

Cannot nest react navigation in component - React Native

I'm having trouble nesting a react-navigation StackNavigator within a component - as detailed here https://reactnavigation.org/docs/intro/nesting#Nesting-a-Navigator-in-a-Component
However, even after following the guide to a T, I'm getting the following error -
route 'Home' should declare a screen
Here is my "GoHome.js" component which, in reference to the guide on https://reactnavigation.org, is the "NavigatorWrappingScreen"
/* #flow */
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
import { Constants, Location, Permissions } from 'expo';
import MainNavigator from '../navigation/MainNavigator';
import AppInfo from '../components/AppInfo/AppInfo';
import { MainStyle } from '../stylesheets/MainStyle';
export default class GoHome extends Component {
constructor(props){
super(props);
}
static navigationOptions = {
header: null,
};
componentWillMount(){
this._getLocationAsync();
}
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
console.log('Error - location access denied');
}else{
let location = await Location.getCurrentPositionAsync({});
console.log(location);
}
}
render() {
return (
<Image style = {MainStyle.imageContainer} source = {require('../assets/bg/bg_main.jpg')}>
<AppInfo />
<MainNavigator navigation = {this.props.navigation} />
</Image>
);
}
}
const styles = StyleSheet.create({
});
GoHome.router = MainNavigator.router;
And here is my MainNavigator.js component, which is the "MainScreenNavigator" component in the guide.
/* #flow */
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
Image
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import Register from '../components/Register/Register';
import Password from '../components/Password/Password';
import AppInfo from '../components/AppInfo/AppInfo';
import { MainStyle } from '../stylesheets/MainStyle';
import GoHome from '../screens/GoHome';
const NavigatorMain = StackNavigator({
Home: {
screen: GoHome
},
Register: {
screen: Register
},
Password: {
screen: Password
}
});
// export default class MainNavigator extends Component {
// render() {
// return (
// <NavigatorMain />
// );
// }
// }
const styles = StyleSheet.create({
});
export default NavigatorMain;
Any help AT ALL would be greatly appreciated.
TIA

React Native navigation - undefined is not an object

I'm new to React native and trying to follow tutorials to learn however can't get navigation between screens to work. I have previously got it working fine with one screen but when adding navigation I get errors.
Following this: https://facebook.github.io/react-native/releases/next/docs/navigation.html
Gives me code like this:
import React from 'react';
import {
StackNavigator,
} from 'react-navigation';
export default class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
title="Go to Jane's profile"
onPress={() =>
navigate('Profile', { name: 'Jane' })
}
/>
);
}
}
class ProfileScreen extends React.Component {
static navigationOptions = {
title: 'Profile',
};
render() {
return (
<Button title="do nothing"/>
);
}
}
const App = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
Trying to run this (through the expo app) results in the error
undefined is not an object (evaluating 'this.props.navigation.navigate')
So am I doing navigation correctly and how do I fix this error?
You need to use AppRegistry.registerComponent in your App.
A nice way of doing this is to create a src directory and then create the 2 js files, HomeScreen and ProfileScreen there. Then create and App.js on the same level as your index.android.js or index.ios.js and include these 2 files and declare the StackNavigator as you did in your code, but instead of const App you need to have const NameOfYourApp, where NameOfYourApp is how you named your project when you ran create-react-native-app.(If it is App, just leave it like that)
Then you need to add this line at the end, AppRegistry.registerComponent('NameOfYourApp', () => NameOfYourApp);
import React from 'react';
import {
StackNavigator,
} from 'react-navigation';
import HomeScreen from './src/HomeScreen'
import ProfileScreen from './src/ProfileScreen'
const NameOfYourApp = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
AppRegistry.registerComponent('NameOfYourApp', () => NameOfYourApp)
The final step is to import your App.js file in your index.android.js or index.ios.js
import './App';

Categories