react-native-navigation V3 crashing the app - javascript

hello i'm trying to implement navigation into my react native app, the app doesn't start, and when it does it displays this error .... (0 , _reactNavigation.StackNavigator) is not a function ... !!
the code below is mostely copy pasted from this blog https://appdividend.com/2018/03/20/react-native-navigation-example-tutorial/#Create_two_screens_for_our_projecte
. i know that due to updates in V3 of react-navigation, you have to wrap StackNavigator in a createAppContainer function before exporting it, so what else am i doing wrong here !!
//the app.js code
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {StackNavigator, createAppContainer} from 'react-navigation';
import Settings from './firstScreen';
import Home from './secondScreen';
import AppNavigator from './navigationControl';
export default class App extends Component {
render() {
return (<AppNavigator/>);
}
}
//the navigationControls.js code
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {StackNavigator, createAppContainer} from 'react-navigation';
import Settings from './firstScreen';
import Home from './secondScreen';
const AppNavigator = StackNavigator({
SettingScreen: {
screen: Settings
},
HomeScreen: {
screen: Home
}
});
export default createAppContainer(AppNavigator);
//the firstScreen.js code
import React, {Component} from 'react';
import {View, Text, Button} from 'react-native';
export class Settings extends Component {
render() {
return (
<View>
<Text>This is the Settings screen</Text>
</View>
)
}
};
export default Settings;
//the scondScreen.js code
import React, { Component } from 'react';
import { View, Text } from 'react-native';
export class Home extends Component {
render() {
return (
<View>
<Text>This is the home screen</Text>
</View>
)
}
}
export default Home;
//package.json file
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "^34.0.1",
"react": "16.8.3",
"react-dom": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-gesture-handler": "~1.3.0",
"react-native-reanimated": "~1.1.0",
"react-native-web": "^0.11.4",
"react-navigation": "^3.12.1"
},
"devDependencies": {
"babel-preset-expo": "^6.0.0"
},
"private": true
}

Change StackNavigator to createStackNavigator
Replace this
import {StackNavigator, createAppContainer} from 'react-navigation
To this
import {createStackNavigator, createAppContainer} from 'react-navigation';
Use something like this
import {createStackNavigator, createAppContainer} from 'react-navigation'; const MainNavigator = createStackNavigator({
Home: {screen: HomeScreen},
Profile: {screen: ProfileScreen}, });
const App = createAppContainer(MainNavigator);
export default App;
Remove export in front of Home and Setting class because you already added export default at the bottom of the class

have you done npm install
npm install
you need that if you have taken an existing project.

Related

React-router component does not update on <Link> navigation

As many other people have had the same issue, I'm struggling to interact with a <Link> element to change routes and render a new component. I am able to click on the link and the path for my application changes in my redux store, but no component gets updated. My root component does not seem to respond to shouldComponentUpdate, even though props are changing and the full setup is similar to how connected-react-router describes it needs to be.
To test
The sample code (git repo) is a MVP (minimum viable product) - it can easily replicate the problem I am seeing.
git clone https://github.com/reZach/electron-webpack-template.git
cd electron-webpack-template
npm i
npm run dev
If you'd prefer to look at files, I've included the necessary files below
index.js
import React from "react";
import ReactDOM from "react-dom";
import Root from "../app/components/core/root";
import store, { history } from "./redux/store/store";
ReactDOM.render(
<Root store={store} history={history}></Root>,
document.getElementById("root")
);
store.js
import { configureStore, getDefaultMiddleware } from "#reduxjs/toolkit";
import { createBrowserHistory } from "history";
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createBrowserHistory();
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;
root.jsx
import React from "react";
import { ConnectedRouter } from "connected-react-router";
import { Provider, connect } from "react-redux";
import Routes from "../core/routes";
class Root extends React.Component {
render() {
return (
<Provider store={this.props.store}>
<ConnectedRouter history={this.props.history}>
<Routes></Routes>
</ConnectedRouter>
</Provider>
);
}
}
export default Root;
routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
routes.json
{
"ENTRY": "/",
"MAIN": "/main"
}
package.json
{
"name": "electron-webpack-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "npm run build-dev-webpack && npm run start-dev-app",
"build-dev-webpack": "webpack --mode development --config ./app/configs/webpack/webpack.config.js",
"start-dev-app": "cross-env NODE_ENV=development electron app/main.js",
"prod": "npm run build-prod-webpack && npm run start-prod-app",
"build-prod-webpack": "webpack --mode production --config ./app/configs/webpack/webpack.config.js",
"start-prod-app": "cross-env NODE_ENV=production electron app/main.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/reZach/electron-webpack-template.git"
},
"keywords": [],
"author": "",
"license": "GPL-3.0-only",
"bugs": {
"url": "https://github.com/reZach/electron-webpack-template/issues"
},
"homepage": "https://github.com/reZach/electron-webpack-template#readme",
"devDependencies": {
"#babel/core": "^7.7.7",
"#babel/plugin-proposal-json-strings": "^7.7.4",
"#babel/plugin-transform-react-jsx": "^7.7.7",
"#babel/preset-env": "^7.7.7",
"babel-loader": "^8.0.6",
"cross-env": "^6.0.3",
"csp-html-webpack-plugin": "^3.0.4",
"devtron": "^1.4.0",
"electron": "^7.1.7",
"html-webpack-plugin": "^3.2.0",
"lockfile-lint": "^3.0.5",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
},
"dependencies": {
"#reduxjs/toolkit": "^1.2.1",
"connected-react-router": "^6.6.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"redux": "^4.0.5"
}
}
This is probably because there is no "exact" word on the Entry route (for App component):
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route>
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
The solution to these routing woes was to add the exact attribute as drazewski suggested, and in addition change the history object I was using for my <ConnectedRouter>. The problem was caused by me using createBrowserHistory and the fact that I am not using a webserver in my application to host my files. The default path of my application when loading my app was file:///C:/...index.html. This is the path value when I looked in my Redux store when the app loaded.
I had to change to use createHashHistory instead, which works when you are not hosting a webserver to host your app. The default path when using createHashHistory is a /, which matches routes.ENTRY in my routes.jsx file and allows me to navigate to /main. Apparently, you can't navigate to another path unless your path matches an existing path you define in your <Route>s (this is what I think what was happening as I described my problem above - although I don't know why my home/page1 component rendered at all then...).
Here
are good references that pointed me in the direction that I had to change my history (here and here). In addition to those links, here is a good blog post (mirror) explaining more in-detail the various types of history for react-router.
new routes.jsx
import React from "react";
import { Switch, Route } from "react-router";
import routes from "../../constants/routes";
import App from "../app/app";
import Page2 from "../page2/page2";
class Routes extends React.Component {
render() {
return (
<Switch>
<Route exact path={routes.ENTRY} component={App}></Route> <!-- updated -->
<Route path={routes.MAIN} component={Page2}></Route>
</Switch>
);
}
}
export default Routes;
new store.js
import { configureStore, getDefaultMiddleware } from "#reduxjs/toolkit";
import { createHashHistory } from "history"; // < updated!
import { routerMiddleware } from "connected-react-router";
import rootReducer from "../reducers/rootReducer";
export const history = createHashHistory(); // < updated!
const store = configureStore({
reducer: rootReducer(history),
middleware: [...getDefaultMiddleware(), routerMiddleware(history)]
});
export default store;

React Native and Apollo: Can't find variable: document

I am getting the error that has been stated on the title, and I am not sure how to get rid of it and make my app run properly.
I have been trying to solve it but can't find a solution yet. The only thing I found that was related to my error was this comment: "You cannot use document in React Native, you can create a backdrop behind the menu then on press backdrop you can hide it." written by Fayeed. Although this may seem to be my answer, I am not sure how to create that backdrop. Here is my code:
import React from 'react';
import ReactDOM from 'react-dom';
import {Route, Link, BrowserRouter as Router} from 'react-router-dom';
import news from './components/News';
import eating from './components/Eating';
import LoginForm from './components/LoginForm';
import ApolloClient from 'apollo-client';
import {ApolloProvider} from 'react-apollo';
import {HttpLink} from 'apollo-link-http';
import {InMemoryCache} from 'apollo-cache-inmemory';
const client= new ApolloClient({
link: new HttpLink({uri:'https://api-useast.graphcms.com/v1/ck25kwqhb10bg01cx4o1i5czu/master'}),
cache:new InMemoryCache()
})
const routing = (
<Router>
<Route path="/" component={LoginForm} />
<Route path="/news" component={News} />
<Route path="/eating" component={Eating} />
</Router>
)
ReactDOM.render((
<ApolloProvider client={client}>
routing
</ApolloProvider>
),
document.getElementById('root')
)
This is my package.json file:
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"apollo-cache-inmemory": "^1.6.3",
"apollo-client": "^2.6.4",
"apollo-link-http": "^1.5.16",
"expo": "^35.0.0",
"graphql": "^14.5.8",
"react": "16.8.3",
"react-apollo": "^3.1.3",
"react-dom": "^16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
"react-native-web": "^0.11.7",
"react-router-dom": "^5.1.2"
},
"devDependencies": {
"babel-preset-expo": "^7.1.0"
},
"private": true
}
I want to be able to load my app without any errors.
I solved it, I had to download react-router-native and not react-router-DOM. That was it. Instead of:
import React from 'react';
import ReactDOM from 'react-dom';
import {Route, Link, BrowserRouter as Router} from 'react-router-dom';
mport ApolloClient from 'apollo-client';
import {ApolloProvider} from 'react-apollo';
import {HttpLink} from 'apollo-link-http';
import {InMemoryCache} from 'apollo-cache-inmemory';
I had to do:
import React, {Component} from 'react';
import {Route, Link, NativeRouter as Router} from 'react-router-native';
import ApolloClient from 'apollo-client';
import {ApolloProvider} from 'react-apollo';
import {HttpLink} from 'apollo-link-http';
import {InMemoryCache} from 'apollo-cache-inmemory';
And replace that DOM render for a class component.

Connecting a Container component to the Redux store in ReactJs but get an error saying BrowserRouter is expecting a string but gets an object

I'm trying to hook up a Container to the redux store but I get this error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: object.
Check the render method of Route.
I'm trying to follow the instructions here:
https://react-redux.js.org/using-react-redux/connect-mapdispatch
My attempts are commented out at the bottom. Swapping either for the normal export default statement produces this error but the normal way works fine so I know this is a problem with connect.
My container:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import axios from 'axios';
//import { bindActionCreators } from 'redux'
import queryString from 'query-string';
import { signIn } from "../actions";
class MomentumContainer extends Component {
state = {display: "Waiting"};
componentWillMount() {
const query = queryString.parse(this.props.location.search);
console.log(`query: ${JSON.stringify(query)}`);
if(query.user_id) {
console.log(`User logged in w/ id: ${query.user_id}`);
//this.props.dispatch(signIn(query.user_id));
}
}
async componentDidMount() {
const dev = process.env.REACT_APP_DEV_SERVER_ENDPOINT;
const prod = process.env.REACT_APP_PROD_SERVER_ENDPOINT;
const base_endpoint = process.env.REACT_APP_DEV_MODE ? dev : prod;
const api_endpoint = `${base_endpoint}momentum`;
//TODO above can be handled on app startup and managed by redux??
//console.log(api_endpoint);
const response = await axios.get(api_endpoint);
this.setState({display: response.data});
}
render() {
return <h1>{this.state.display}</h1>
}
}
// // Tried this
// const actionCreators = { signIn };
// export default connect(null, actionCreators)(MomentumContainer);
// // Tried this
//export default connect()(MomentumContainer);
// This works
export default MomentumContainer;
My index.js file:
import React from "react";
import ReactDOM from "react-dom";
import {Provider} from "react-redux";
import {createStore, compose, applyMiddleware} from "redux";
import thunk from "redux-thunk";
import promise from 'redux-promise-middleware';
import logger from "redux-logger";
import registerServiceWorker from "./registerServiceWorker";
import "./index.css";
import App from "./App";
import {BrowserRouter, Route, Switch} from "react-router-dom";
import reducers from './reducers';
import MomentumContainer from "./containers/MomentumContainer";
const { REACT_APP_DEV_MODE } = process.env;
const dev_mode = JSON.stringify(REACT_APP_DEV_MODE) === JSON.stringify("true");
const middleware = applyMiddleware(promise, thunk, logger);
let store_dev;
if (dev_mode === true) {
console.log('App starting in development mode.');
const allStoreEnhancers = compose(
middleware,
window.devToolsExtension && window.devToolsExtension()
);
store_dev = createStore(reducers, {}, allStoreEnhancers)
} else {
console.log('App starting in production mode');
}
const store_production = createStore(reducers, {}, middleware);
const store = dev_mode ? store_dev : store_production;
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route path="/" exact component={App} />
<Route path="/Momentum" exact component={MomentumContainer} />
</Switch>
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
registerServiceWorker();
My package.json:
{
"name": "ticker-alert-frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"#material-ui/core": "^3.9.3",
"ajv": "^6.10.0",
"axios": "^0.18.0",
"materialize-css": "^1.0.0-rc.2",
"query-string": "^6.1.0",
"react": "^16.8.6",
"react-dom": "^16.4.0",
"react-redux": "^7.0.3",
"react-router-dom": "^4.3.1",
"react-scripts": "1.1.4",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-promise": "^0.6.0",
"redux-promise-middleware": "^6.1.0",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Any help/suggestions would be greatly appreciated!
After reading here (https://github.com/ReactTraining/react-router/issues/4354) about a similar issue, and seeing a suggestion to update react-router-dom, I tried updating that package to version 5.0.0 from 4.3.1 and it didn't work.
After updating the rest of my packages by running npm update --save my app is working. If anyone is having a similar problem I recommend running this command.

React Native Error - Invariant Violation: Element type is invalid

I am following a Udemy course to build a demo react native application. So far, the application consists of 3 components - App, AlbumList & AlbumDetail. The code for each is listed below.
App.js
import React, { Component } from 'react';
import View from 'react-native';
import AlbumDetail from './AlbumDetail'
import axios from 'axios';
class AlbumList extends Component {
constructor(props){
super(props)
this.state = { albums: [{"title": "one"}, {"title": "two"}] }
}
renderAlbums() {
return this.state.albums.map(album =>
<AlbumDetail key={album.title} album={album} />
);
}
render() {
return (
<View>
{ this.renderAlbums() }
</View>
);
}
}
export default AlbumList;
AlbumList.js
import React, { Component } from 'react';
import View from 'react-native';
import AlbumDetail from './AlbumDetail'
import axios from 'axios';
class AlbumList extends Component {
constructor(props){
super(props)
this.state = { albums: [{"title": "one"}, {"title": "two"}] }
}
renderAlbums() {
return this.state.albums.map(album =>
<AlbumDetail key={album.title} album={album} />
);
}
render() {
return (
<View>
{ this.renderAlbums() }
</View>
);
}
}
export default AlbumList;
AlbumDetail.js
import React from 'react';
import { View, Text } from 'react-native';
const AlbumDetail = (props) => {
return (
<View>
<Text>{props.album.title}</Text>
</View>
)
};
export default AlbumDetail;
package.json
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject"
},
"dependencies": {
"axios": "^0.18.0",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0"
},
"private": true
}
When I run npm start and launch the app in a mobile device(One Plus 3T running Android 8.0.0), I get the following error
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
This error is located at:
in AlbumList (created by App)
in RCTView (at View.js:44)
in App (at withExpoRoot.js:22)
...
...
I went through a few questions posted in StackOverflow and most of them refer to incorrect way of exporting and importing components. As far as I can see, I am exporting and importing components correctly here but still get the error.
Feel free to add a comment if you need more information. Any help debugging the issue is appreciated.
import statement is wrong here at App.js and AlbumDetail.js
change it with
import {View} from "react-native"

React-Router cannot read property string of undefined

I am new to React and I am building my first application with React, Redux, and React Router, so far I have successfully set up my boiler plate, however when I want to use React-Router and create routes I get the following error
TypeError: Cannot read property 'string' of undefined
./node_modules/react-router-dom/es/BrowserRouter.js
node_modules/react-router-dom/es/BrowserRouter.js:38
35 | }(React.Component);
36 |
37 | BrowserRouter.propTypes = {
> 38 | basename: PropTypes.string,
39 | forceRefresh: PropTypes.bool,
40 | getUserConfirmation: PropTypes.func,
41 | keyLength: PropTypes.number,
This only happens when I try to import and use
import { BrowserRouter, Route } from 'react-router-dom';
Here is my index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store'
import { BrowserRouter, Route } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
class Hello extends Component {
render(){
return(
<div>Hello</div>
)
}
}
class GoodBye extends Component {
render(){
return(
<div>GoodBye</div>
)
}
}
ReactDOM.render(<Provider store={store}>
<BrowserRouter>
<Route path="/hello" component={Hello}/>
<Route path="/goodbye" component={GoodBye}/>
</BrowserRouter>
</Provider>, document.getElementById('root'));
registerServiceWorker();
And my package.json
{
"name": "reactreduxrouterblog",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.16.2",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"react-router": "^2.0.0-rc5",
"react-router-dom": "^4.0.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-promise-middleware": "^4.4.1",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"react-scripts": "1.0.14"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Any knowledge will be welcomed thanks!
Update your react-router-dom in package.json: react-router-dom ^4.2.2
Sometimes it may cause due to incompatible versions of "react-router-dom" and "react-router-prop-types". For me it worked with following configuration.
react-router-dom:"^4.2.2",
react-router-prop-type:"^3.2.1"
Try adding the PropTypes package to your app.
basename: PropTypes.string
Looks like you are just missing that package.
EDIT:
Be sure to run npm install to install all dependencies.
import React from 'react'; <--as normal
import PropTypes from 'prop-types'; <--add this as a second line
App.propTypes = {
monkey: PropTypes.string, <--omit "React."
cat: PropTypes.number.isRequired <--omit "React."
};
//Wrong: React.PropTypes.string
//Right: PropTypes.string

Categories