I am creating a simple app with ReactJS and Cordova. The app works fine when I run it through reacts npm start. However when I do a npm run build and copy the build folder into the www folder of my cordova project, I get a blank screen when I run it in android. If I do a cordova run browser the router is not working and its landing at index.html. I think I have narrowed it down to a router issue with cordova where route is not setting the page to home. Has anyone else had an issue like this? I created my reactJS project using npm create-react-app.
https://github.com/bscott8605/reactRouterTest
Folder Structure
import React, { Component } from 'react'
import { BrowserRouter as Router } from 'react-router-dom'
import { Switch, Route } from 'react-router'
import Home from './Home'
import AddNote from './AddNote'
import Note from './Note'
class Main extends Component {
render() {
let notes;
if(this.props.notesList)
{
//console.log(this.props);
notes = this.props.notesList.map(note => {
return(
<Note key={note.title} note={note} />
);
});
}
return (
<Router>
<div>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/AddNote' component={AddNote}/>
{/*<Route exact path='/' render={(props) => (<Home {...props} data={notes}/>)}/>
<Route exact path='/AddNote' render={(props) => (<AddNote {...props} addNoteMethod={this.props.addNoteMethod}/>)}/>*/}
</Switch>
</div>
</Router>
);
}
}
export default Main;
Change BrowserRouter to Router
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import createHistory from 'history/createHashHistory'
import store from './app/redux/store';
import Layout from './app/pages/layout';
import Routes from './app/pages/routes';
import './app/assets/favicon.ico';
import './app/assets/scss/main.scss';
const history = createHistory();
console.log(history);
const Dom = (
<Provider store={store}>
<Router history={history}>
<Layout>
<Routes />
</Layout>
</Router>
</Provider>
);
ReactDOM.render(
Dom,
document.getElementById('app'),
);
Related
App.js:
import React, { Component } from 'react';
import {View,Text} from 'react-native';
import { createDrawerNavigator } from 'react-navigation-drawer';
import {createAppContainer} from 'react-navigation';
import Epics from './screens/tmp';
import Pager from './screens/Pager';
const DrawerNavigator = createDrawerNavigator({
Home: {screen: Epics},
Page: {screen: Pager}
},{initialRouteName: 'Home'});
const Stack = createAppContainer(DrawerNavigator);
export default class App extends Component {
render() {
return <Stack />;
}
}
Trying to invoke fetch API everytime a user lands on screen using navigation addListner event
componentDidMount() {
this.loadFeed(); // fetch API
const { navigation } = this.props;
this.focus = navigation.addListener('willFocus', () => {
this.loadFeed(); // fetch API
});
}
React Navigation version from package.json:
"react-navigation": "^4.2.2"
"react-navigation-drawer": "^2.4.2"
Is there a better way to detect an active screen on app and invoke the fetch API? Or fix for the given error below?
Type Error: undefined is not an object (evaluating 'navigation.addListner'):
Error when the app launches
Update
I am trying to replicate following example in snack: https://snack.expo.io/HkrP8YPIf
What am I doing wrong? (I am new to React Native, please help me understand)
Try using the NavigationEvents component shipped with react-navigation 4.x. Just nest it anywhere inside your screen's render method.
Example:
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={() => console.log('Screen will be in focus')}
onDidFocus={() => console.log('Screen is in focus')}
onWillBlur={() => console.log('Screen will blur')}
onDidBlur={() => console.log('Screen blurred')}
/>
{/*
other code
*/}
</View>
);
export default MyScreen;
This just means that navigation doesn't exist. So it looks like the component is supposed to receive it via props and isn't. That's all I can tell from this code.
Check your props keys, agree with James. Have one suggestion here, since you're expecting a props, you should handle this common error whether key exist or not(if else)
I have been searching for a solution for a long time, but surprisingly, I think nobody has faced it yet. So I am posting it.
I have created a simple Drawer Navigator with React Navigation V3. I have added a Menu icon, and when I click it, the drawer appears as it should be. But, no hand gesture is working. Swiping from left to right don't do anything. Even when the drawer is open, tapping on empty space doesn't close the drawer.
Here is my code:
import {
createStackNavigator,
createSwitchNavigator,
createAppContainer,
createDrawerNavigator
} from 'react-navigation';
import Home from './screens/Home';
import LoginForm from './screens/LoginForm';
import Articles from './screens/Articles';
const AuthStack = createStackNavigator({
LoginScreen: LoginForm
});
const AppStack = createDrawerNavigator({
HomeScreen: Home,
ArticlesScreen: Articles
});
const RootNavigator = createSwitchNavigator(
{
Auth: AuthStack,
App: AppStack
},
{
initialRouteName: 'Auth'
}
);
export default createAppContainer(RootNavigator);
I have found the solution. React Navigation depends on the react-native-gesture-handler library. In the Installation section of React Navigation docs, it only says to create link by using the command react-native link. This is enough for iOS. But for Android, you have to edit the MainActivity.java file, so that the gesture handler library can work as expected:
import com.facebook.react.ReactActivity;
+ import com.facebook.react.ReactActivityDelegate;
+ import com.facebook.react.ReactRootView;
+ import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "Example";
}
+ #Override
+ protected ReactActivityDelegate createReactActivityDelegate() {
+ return new ReactActivityDelegate(this, getMainComponentName()) {
+ #Override
+ protected ReactRootView createRootView() {
+ return new RNGestureHandlerEnabledRootView(MainActivity.this);
+ }
+ };
+ }
}
Refer to the documentation: https://kmagiera.github.io/react-native-gesture-handler/docs/getting-started.html
Actually, it's nowhere stated in React Navigation documentation to modify any files, as it is specific to react-native-gesture-handler and not React Navigation. I am keeping the answer here so it may help others.
UPDATE: The latest docs of React Navigation addresses this issue
In the index.js of your project just use gestureHandlerRootHOC:
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler'
AppRegistry.registerComponent(appName, () => gestureHandlerRootHOC(App));
resource: https://github.com/react-navigation/drawer/issues/105#issuecomment-540667009
Update:
In React Navigation > 5.x
Just put react-native-gesture-handler at the beginning of root index.js
import 'react-native-gesture-handler';
Seems to be fixed in versions above 0.61.0, but for older versions this worked for me.
In the index.js :
. . .
import {gestureHandlerRootHOC} from 'react-native-gesture-handler';
AppRegistry.registerComponent(appName, () => gestureHandlerRootHOC(App));
. . .
React native docs updated this issue and you can find a section named Installing dependencies into a bare React Native project in the below link
https://reactnavigation.org/docs/en/getting-started.html#installation
I am trying to implement stacknavigation using react-navigation. When I am creating a stacknavigation const and calling in my default screen it is giving me this error.
Route 'Main' should declare a screen. For example:
import MyScreen from './MyScreen';
...
Home: {
screen: MyScreen,
}
My StackNavigation code is here
import React from 'react';
import {View, Text } from 'react-native';
import Register from './Register';
import Main from './Main';
import { StackNavigator } from 'react-navigation';
const ScreenList = StackNavigator({
Main: {
screen: Main,
},
Register: {
screen: Register,
},
});
export default ScreenList;
And this is the main and default screen
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Card, Button, CardSection } from '../components/common/Index';
import Login from '../components/Login';
import ScreenList from './ScreenList';
export default class Main extends Component {
render() {
return (
<View>
<Button>Register</Button>
</View>
);
}
}
This is an issue with react-native-navigation not yet being compatible with React 0.52.0
More information on this issue can be found on this specific issue tracked on Github.
Edit: a quick fix I just implemented to unblock myself while the project contributors figure out a solid solution was to add the missing interface (ReactInstanceDevCommandsHandler.java) directly into my react-native-navigation project.
I am going through the react-native tutorials on lynda.com, "React-Native: Building Mobile Apps". The difference lies in the fact that I am using WebStorm to develop JavaScript based apps. I've created the files according to the tutorial:
appContainer.js:
import React, { Component } from "react";
import { Drawer, View } from "react-native";
import { Navigator } from "react-native";
export default class AppContainer extends Component {
constructor(props){
super(props);
this.state = {
store: {},
toggled: false,
theme: null
}
}
toggleDrawer(){
this.state.toggled ? this._drawer.close() : this._drawer.open();
}
openDrawer(){
this.setState({toggled: true});
}
closeDrawer(){
this.setState({toggled: false});
}
renderScene(route, navigator){
switch(route){
default: {
return null
}
}
}
configureScene(route, routeStack){
return Navigator.SceneConfigs.PushFromRight;
}
render(){
return (
<Drawer
ref={(ref) => this._drawer = ref}
type="displace"
content={<View style={{backgroundColor: "#000", height: 1000}}
/>}
onClose={this.closeDrawer.bind(this)}
onOpen={this.openDrawer.bind(this)}
openDrawerOffset={0.2}
>
<Navigator
ref={(ref) => this._navigator = ref}
configureScene={this.configureScene.bind(this)}
renderScene={this.renderScene.bind(this)}
/>
</Drawer>
);
}
}
index.ios.js:
import React, { Component } from 'react';
import {
AppRegistry
} from 'react-native';
import AppContainer from "./app/appContainer";
export default class dinder extends Component {
render() {
return (
<AppContainer/>
);
}
}
AppRegistry.registerComponent('dinder', () => dinder);
Run/Debug Configuration screen:
However, when I run the app by selecting run 'ios' from the run drop down windows, I am receiving the following error in the emulator window:
Can someone please explain how I can fix this issue within the confines of the code presented for the tutorial that I pasted?
In React-Nav 0.44.3 the Navigator has been deprecated: https://github.com/facebook/react-native/releases/tag/v0.44.3, so is not really a webstorm's configuration's issue.
To fix this, you can follow this Github issue, install the react-native-deprecated-custom-components package through npm or yarn.
And then in your appContainer.js, replace your
import { Navigator } from "react-native";
with
import NavigationExperimental from 'react-native-deprecated-custom-components';
And change all your Navigator call to NavigationExperimenal.Navigator
I'm following the tutorial from meteor and angular 2 and when I reach the step 11 Running your app on Android or iOS with PhoneGap I can't make it work on my android device.
This is the output I get from the console.
Error: Uncaught (in promise): Error: Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: The selector "app" did not match any elements
This is what I have so far in my app.component.ts file:
import { Component } from '#angular/core';
import template from './app.component.html';
#Component({
selector: 'app',
template
})
export class AppComponent {}
The app works perfectly on the web browser. I think that can be a problem with the router, but I'm not quite sure.
This is the code from the app.routes.ts
import { Route } from '#angular/router';
import { Meteor } from 'meteor/meteor';
import { PartiesListComponent } from '../parties/parties-list.component';
import { PartyDetailsComponent } from '../parties/party-details.component';
export const routes: Route[] = [
{ path: '', component: PartiesListComponent },
{ path: 'party/:partyId', component: PartyDetailsComponent}
];
This is the index.html:
<head>
<base href="/" />
</head>
<body>
<app>Loading...</app>
</body>
And this is the app.component.html
<div>
<router-outlet></router-outlet>
</div>
It is supossed to redirect to the PartiesListComponent but just throw that error and stucks on loading. Thank you.
SOLVED
This is the original code in the main.ts (Extracted from the website of the tutorial)
import 'angular2-meteor-polyfills';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './imports/app/app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
I've just find that this tutorial is obsolete (again) and there's a new way to bootstrap applications.
With the next code the app works fine on android.
import 'angular2-meteor-polyfills';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { enableProdMode } from '#angular/core';
import { Meteor } from "meteor/meteor";
import { AppModule } from './imports/app/app.module';
enableProdMode();
Meteor.startup(() => {
platformBrowserDynamic().bootstrapModule(AppModule);
});
I hope this help someone.