index.js configuration with react-native? - react-native

I'm currently trying to implement react-navigation into my RN app. RN documentation seems to say that index.js is a required file for RN projects but the first react-navigation example shows all of the initial code in App.js with no index.js file:
https://snack.expo.io/#react-navigation/auth-flow-v3
Is the index.js file only required for standalone RN projects which are not built on Expo? Maybe Expo handles this automatically behind the scenes? The index.js file appears to be required for my standalone RN app and the render() implementation appears to be required in index.js as well. The problem appears to be that the render() implementation in my index.js appears to override whatever is in App.js. Ie I'm expecting initialRouteName: 'AuthLoading' in the App.js configuration to redirect to my AuthLoading component but App.js logic appears to get superceded by the index.js render() implementation.
So what is the proper way to get my index.js and App.js to support react-navigation integration? I'm open to ditching index.js for an alternative implementation/configuration, I just have it in my project because my understanding is that it's required.

I don't really get your confusion but still, this is how it would look.
First, your index.js would be completely normal. It has to look like this or similar:
//index.js
import { AppRegistry } from 'react-native'
import App from './App'
import { name as appName } from './app.json'
AppRegistry.registerComponent(appName, () => App)
This is just normal, right? Then, let's see how it would be in App.jsx
//App.jsx
import React, { Component } from 'react'
import AppContainer from './fromSomeRoute'//replace by your own
export default class App extends Component {
render() {
return (
<AppContainer />
)
}
}
And what is exactly AppContainer? just the component you exported from the file you are using for react-navigation. In here, there is no need to create a class or something like that, you can just create it like this
//fromSomeRoute.jsx
import React from 'react'
import { createStackNavigator, createSwitchNavigator, createAppContainer } from 'react-navigation'
import YourScreen from './YourPathToYourScreen'
const YourScreenStack = createStackNavigator({
YourScreen: {
screen: YourScreen,
navigationOptions: () => ({ //Look documentation for further info
header: null,
}),
},
})
const AppContainer = createAppContainer(
createSwitchNavigator(
{
Screen: YourScreenStack,
//Create more Stacks and add them in here
},
{
initialRouteName: 'Screen',
},
),
)
export default AppContainer

Related

Invariant Violation: "main" has not been registered While running react-native app

This is my folder structure. I have started this app with expo. Somehow i am not able to run it because of the following error.
Rootstack.js
import React from 'react';
import { createSwitchNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import LoginComponent from "../component/login/login";
import HomeComponent from "../component/home/home"
const AuthNav = createStackNavigator({
Login:{
screen : LoginComponent,
navigationOptions:{
headerShown: false
}
},
});
const AppNav = createStackNavigator({
Home:{
screen : HomeComponent,
tabBarLabel: 'Home',
navigationOptions:{
headerShown: false
}
},
});
const switchNav = createSwitchNavigator({
AuthNav,
AppNav
},{
initialRouteName:"AuthNav"
});
export default switchNav;
App.js inside stack folder
import { createAppContainer } from 'react-navigation'
import App from './stack/RootStack'
import { AppRegistry } from 'react-native';
AppRegistry.registerComponent('main',() => App);
export default createAppContainer(App);
main app.js
import App from './src/App.js';
export default App;
Error
Invariant Violation: Tried to register two views with the same name RNCSafeAreaProvider
Error 2
Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.
Which part i am doing wrong here .
The meaningful exception that you are seeing here is:
Invariant Violation: Tried to register two views with the same name RNCSafeAreaProvider
The "main" has not been registered is a red herring, it only happened because the other error.
The RNCSafeAreaProvider exception is happening because you have multiple copies of react-native-safe-area-context in your app. You may be using a library that includes it as a dependency in addition to having it installed in your app. If you use yarn, you can run yarn why react-native-safe-area-context to see where it's coming from. Try running expo install react-native-safe-area-context and if that doesn't help you can use yarn resolutions to override the version used by the package that depends on it.
The issue is most likely linked to registering your App Multiple times.
Keep all your navigation logic in RootStack.js and avoid using createAppContainer() in your app.js
AppRegistry.registerComponent('main',() => App) should be the final statement after configuring your navigation.
Importing App.js into main app.js means you are registering the main component twice(you should only have one output file). React uses index.js as the default output.
Use this instead App.js inside stack folder:
import { createAppContainer } from 'react-navigation'
import App from './stack/RootStack'
//Remove these 2 lines below
import { AppRegistry } from 'react-native';
AppRegistry.registerComponent('main',() => App);
export default createAppContainer(App);
In your main app.js
import App from './src/App.js';
// Use it here
import { AppRegistry } from 'react-native';
AppRegistry.registerComponent('main',() => App);
export default App;

Reference Error: can't find variable in React Native

I'm getting this error when i run the app on android
My AppNavigation code as follow
import React, {Component} from 'react'
import { createStackNavigator } from 'react-navigation-stack'
import Home from '../pages/Home'
import DetailsAdd from '../pages/DetailsAdd'
import ImagesAdd from '../pages/ImagesAdd'
const AppNavigation = createStackNavigator(
{
DetailsAdd: { screen: DetailsAdd },
ImagesAdd: { screen: ImagesAdd },
Home: { screen: Home },
},
{
initialRouteName: 'Home'
}
)
export default AppNavigation
class App extends React.Component {
render() {
return <AppNavigator/>;
}
}
ImagesAdd Class path is correct, How can I fix this issue?
Have you got any app container? if you not, you should check this link.
important note from React Navigation Docs
createStackNavigator is a function that returns a React component. It takes a route configuration object and, optionally, an options object (we omit this below, for now). createAppContainer is a function that returns a React component to take as a parameter the React component created by the createStackNavigator, and can be directly exported from App.js to be used as our App's root component.

React navigation v3.x and push notifications listener using Expo

I am working on a React Native project (wrapped-up using Expo) with react navigation v3. So, now I decided to enable real-time push notifications provided by Expo. My goal is to submit some custom data together with the push notification itself and then, once it goes on the device and I open the notification to navigate/route/redirect the app to a specific screen that I have defined. I have configured the notifications, I get expo tokens, I receive the notification, it goes in the handler but when I try to apply the navigation that I use throughout my whole app:
this.props.navigation.navigate('RouteName', {data:{...}})
I am getting undefined. I guess we are somehow not in the context of react navigation and that's why some other approach is required. I just don't know what it is.
The structure of my app is as follows:
HomeStack.js
import { createStackNavigator } from 'react-navigation';
import HomeScreen from '../screens/HomeScreen'
import MailboxItemsScreen from '../screens/MailboxItemsScreen'
import MailboxItemDetailsScreen from '../screens/MailboxItemDetailsScreen'
export default createStackNavigator({
Home: HomeScreen,
MailboxItems: MailboxItemsScreen,
MailboxItemDetails : MailboxItemDetailsScreen
});
SettingsStack.js
import { createStackNavigator } from 'react-navigation';
import SettingsScreen from '../screens/SettingsScreen'
export default createStackNavigator({
Settings: SettingsScreen
});
AppNavigator.js
import React from 'react';
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons'
import HomeStack from './HomeStack'
import SettingsStack from './SettingsStack'
const TabNavigator = createBottomTabNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
tabBarIcon:({tintColor})=>(
<Icon name="ios-home" color={tintColor} size={24}/>
)
}
},
Settings: {
screen: SettingsStack,
navigationOptions: {
tabBarIcon:({tintColor})=>(
<Icon name="ios-settings" color={tintColor} size={24}/>
)
}
}
});
export default createAppContainer(TabNavigator);
Then I use the TabNavigator in my App.js. It is quite common structure I just don't know how to do the navigation between screens in my push notification handler method.
It is likely that you already added a listner at root component's constructor or componentDidMount() like that:
Notifications.addListener(this._handleNotifications)
and as the expo document says, you tried to navigate to other screen in _handleNotifications function.
In my case, although navigation structure is slightly different from yours, I added listner at HomeScreen's componentDidMount() and defined _handleNotifications function within HomeScreen component, not at root component (App.js).
Brief version of my `_handleNotifications function is as below:
_handleNotifications = async (notification) => {
const {a, b, c} = notification.data;
const {origin} = notification;
if (origin === 'selected') {
this.props.navigation.push('History', {
a,
b,
c,
})
} else { // origin is 'received'
// show notification at the top of my app instead of navigate to other screen
}
}
if user press notification, then notification is delivered to my app's _handleNotifications function, and since the origin is 'selected', I pushed to other screen called 'History' with parameters received from notification.data.
In my case, that works very well.
Since, the behavior of Android and iOS differs slightly, the event handler should do some more jobs.
I implemented it with Expo v32.0.0 and react navigation 3.x.x.
Hope this helps.

Undefined is not an object React Native StackNavigator

I have been trying to get a simple React Native StackNavigation example app working, however I keep getting an
TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')
I am not expecting the app to navigate anywhere at this stage, simply deploy with an app bar and some arbitrary text.
import React, { Component } from 'react';
import {AppRegistry, Text} from 'react-native';
import {StackNavigator} from 'react-navigation';
export default class App extends React.Component {
static navigationOptions = {
title: 'Home',
};
render() {
const { navigate } = this.props.navigation;
return (
<Text> Hello World </Text>
);
}
}
const appScreens = StackNavigator({
Home: {screen: App},
})
AppRegistry.registerComponent('IntervalTimer', () => appScreens);
The error is reporting on the const { navigate } = this.props.navigation; declaration. And removing this line does allow the app to deploy but with no header as I would expect.
StackNavigator was installed using NPM and is being imported into the app fine.
There are similar questions posted and I have tried their suggestions. Appreciate any help you can offer!
You can add initialRouteName on StackNavigator's option. Try this.
import React, { Component } from 'react';
import {AppRegistry, Text} from 'react-native';
import {StackNavigator} from 'react-navigation';
class App extends React.Component {
static navigationOptions = {
title: 'Home',
};
render() {
const { navigate } = this.props.navigation;
return (
<Text> Hello World </Text>
);
}
}
export const appScreens = StackNavigator({
Home: { screen: App }
},{
initialRouteName: Home
})
AppRegistry.registerComponent('IntervalTimer', () => appScreens);
If this is just that the prop might have a chance of being undefined, you can just check for undefined.
const { navigate } = this.props.navigation || {};
Assuming at some point the navigation is defined in render, the above should be safe to use. You can try logging it and see if it is always undefined or it gets defined at some point.
console.log(navigate)
The output might be...
undefined
undefined
//defined

Stack Navigator Works On Android But iOS Broken

Our React Native Project, uses react-navigation Stack navigator. It perfectly running in Android but in ios it gives an error which "Raw Text must be wrapped in an explicit " When we try to navigate between Page.
In ios only first page loading. For example, Default 'Main Page' is the first page in order so android and ios emulator both open the first page. Then if we try to navigate between them in android navigaton works but in ios we get "Raw text Error".
And if we change firs page of stack navigator ios also loaded first page correctly but not navigate between them as expected.
We think navigated pages may be problem, so we create a blank page and navigate to there, but issue still continue in iOS.
I am really glad to hear suggestions.
This is how we navigate between pages:
this.props.navigation.navigate('ProfileSayfa');
This is our index.android.js and also index.android.ios:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import {StackNavigator,DrawerNavigator } from "react-navigation";
import LoginPage from "./src/pages/login-page/login-page";
import MainPage from "./src/pages/main-page/main-page";
import MekanAraSonuc from "./src/pages/MekanAra/MekanAraSonuc";
import MekanAra from "./src/pages/main-page/tabs/mekan_ara";
import NewsTab from "./src/pages/main-page/tabs/news-tab";
import StartPage from "./src/pages/start-page/start-page";
import AllMekan from "./src/pages/AllMekan/AllMekan";
import MekanSayfa from "./src/pages/MekanSayfa/MekanSayfa";
import RezervasyonSayfa from "./src/pages/MekanSayfa/RezervasyonSayfa";
import FirsatSayfa from "./src/pages/MekanSayfa/FirsatSayfa";
import EtkinlikSayfa from "./src/pages/MekanSayfa/EtkinlikSayfa";
import ProfileSayfa from "./src/pages/MekanSayfa/ProfileSayfa";
import EtkinlikSonuc from "./src/pages/AllMekan/EtkinlikSonuc";
import FirsatlarSonuc from "./src/pages/AllMekan/FirsatSonuc";
import IconME from 'react-native-vector-icons/FontAwesome';
import Drawer from "./src/pages/MyComponents/Drawer";
import SearchForm from "./src/pages/MyComponents/SearchForm";
import RezervasyonForm from "./src/pages/Forms/RezervasyonForm";
import FirsatForm from "./src/pages/Forms/FirsatForm";
import CalendarListView from "./src/pages/Forms/CalendarListView";
export default class moreAwesome extends Component {
render() {
return (
<LoginApp
ref={nav => {
this.navigator = nav;
}}
/>
);
}
}
const LoginApp = StackNavigator({
MainPage: {
screen: MainPage,
},
LoginPage: { screen: LoginPage },
MekanAraSonuc:{screen:MekanAraSonuc},
MekanAra:{screen:MekanAra},
NewsTab:{screen:NewsTab},
AllMekan:{screen:AllMekan},
MekanSayfa:{screen:MekanSayfa},
FirsatSayfa:{screen:FirsatSayfa},
EtkinlikSayfa:{screen:EtkinlikSayfa},
EtkinlikSonuc:{screen:EtkinlikSonuc},
FirsatlarSonuc:{screen:FirsatlarSonuc},
ProfileSayfa:{screen:ProfileSayfa},
RezervasyonSayfa:{screen:RezervasyonSayfa},
SearchForm:{screen:SearchForm},
RezervasyonForm:{screen:RezervasyonForm},
FirsatForm:{screen:FirsatForm},
CalendarListView:{screen:CalendarListView},
});
AppRegistry.registerComponent('myproje', () => moreAwesome);
Apperantly, when you create static Navigation Options for an page, "title" can be empty string in Android but not on iOS.
When we change this,
static navigationOptions = ({ navigation }) => {
return {
title: '',
};
};
To this:
When we change this,
static navigationOptions = ({ navigation }) => {
return {
title: ' ',
};
};
And Also be careful intial page gives this error not target page!