How to fix util could not be found in React Native? - javascript

I am new to react native, I created a sample application for navigation between screen but I am facing some issue. I have attached the screen shot.
code I have used in App.js
import React from 'react';
import {Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation';
import FirstScreen from './screens/FirstScreen'
import SecondScreen from './screens/SecondScreen'
const Navigation = StackNavigator({
First: {screen: FirstScreen},
Second: {screen: SecondScreen}
});
export default Navigation; // Export your root navigator as the root component
second screen code:
import React from 'react';
import {Text, View, Button} from 'react-native';
const util = require('util');
export default class SecondScreen extends React.Component {
static navigationOptions = {
title: 'Second screen',
};
render() {
console.log("this.props.navigation.state = " + util.inspect(this.props.navigation.state, false, null));
var {params} = this.props.navigation.state;
return (
<View>
<Text>This is screen 2</Text>
<Text>Params from screen1 : {params.name}, email = {params.email}</Text>
</View>
);
}
}
These code I got form github.

Refer below link. You have to clear cache and run again.
How to clear react-native cache?
There would be a chance for a path issue or some error in second screen code. Make a simple hello world on the second screen.

Related

Attempted to assign to readonly property error

I am trying to nest a stack navigation inside a drawer navigation and I get
Device: (895:881) Attempted to assign to readonly property.
Evaluating module://react-native-screens.js
Evaluating module://react-navigation-drawer.js
Evaluating module://routes/drawer.js.js
Evaluating module://App.js.js
Loading module://App.js
The Drawer nests two stack navigators. homeStack and drawerStack. Drawer is the exported in App.js. Can someone please explain what am I doing wrong?
Drawer.js
import * as React from 'react';
import { createDrawerNavigator } from 'react-navigation-drawer';
import { createAppContainer } from 'react-navigation';
import HomeStack from './homeStack';
import DrawerStack from './drawerStack';
const screens = {
Home: {
screen: HomeStack,
},
About: {
screen: DrawerStack,
}}
const Drawer = createDrawerNavigator(screens);
export default Drawer;
App.js
import * as React from 'react';
import Drawer from './routes/drawer'
export default class App extends React.Component {
render() {
return (
<Drawer />
);
}
}

"undefined is not an object (evaluating 'Component.router')" when running a boiler plate react-navigation app

I am new to react-native and wanted to try out react-navigation.
But when I try to run a basic app it gives me 'undefined is not an object(evaluating 'Component.router)' error. Please help
here's a screenshot of the error
https://i.gyazo.com/fa89defeff8bef894f509f1511f9b1ae.png
Here's the only thing I changed in the default project except for installing
react-navigation and react-native-gesture-handler
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {createAppContainer,
createSwitchNavigator,
createStackNavigator} from 'react-navigation';
type Props = {};
export default class App extends Component<Props> {
render() {
return <AppNavigator/>;
}
}
class MainScreen extends Component{
render(){
return <Text>Hi</Text>
}
}
const AppNavigator = createAppContainer(SwitchNavigator);
const SwitchNavigator = createSwitchNavigator({
MainScreen : MainScreen,
});```
You have two issues in your code
(1) You are trying to access SwitchNavigator before it's declaration.
(2) You are doing MainScreen : MainScreen, which will cause an error.
const SwitchNavigator = createSwitchNavigator({
MainScreen,
});
or
// optionally pass an object to your route, with screen, navigation options
const SwitchNavigator = createSwitchNavigator({
MainScreen: { screen: MainScreen },
});
const AppNavigator = createAppContainer(SwitchNavigator);
In your code you are accessing SwitchNavigator before its declaration.
let and const variables can be accessed only after their declarations.
Example:
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
const a = 10;
source: MDN docs
That being said, your code should be:
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {createAppContainer,
createSwitchNavigator,
createStackNavigator} from 'react-navigation';
type Props = {};
export default class App extends Component<Props> {
render() {
return <AppNavigator/>;
}
}
class MainScreen extends Component{
render(){
return <Text>Hi</Text>
}
}
const SwitchNavigator = createSwitchNavigator({
MainScreen : MainScreen,
});
const AppNavigator = createAppContainer(SwitchNavigator);
seems ok except you forgot to import MainScreen
import { MainScreen } from '..pathname'

How to solve: Can't call setState(or forceUpdate) on an unmounted component warning in React-Native?

In my React-native project in the HomeScreen, I get some values from AsyncStorage. After getting this value I compare it and take decision in which screen it will go next.
If the getValue is null then it will go the WelcomeScreen and if it is not null then it will go the HomeDrawer Screen.
Here I have provided the code-
import React from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import {StackNavigator} from 'react-navigation';
import WelcomeScreen from './WelcomeScreen';
import LoginScreen from './components/LoginScreen';
import NoteMeHome from './components/NoteMeHome';
import HomeDrawer from './HomeDrawer/HomeDrawer';
import SettingsScreen from './components/SettingsScreen';
class HomeScreen extends React.Component {
state = {
getValue: '',
}
async componentDidMount() {
const token = await AsyncStorage.getItem('toke');
this.setState({ getValue: token });
}
render() {
console.log('#ZZZ:', this.state.getValue);
if(this.state.getValue !== null) {
return (
<AppStackNavigator/>
);
} else {
return (
<AppStackNavigator2/>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
const AppStackNavigator = new StackNavigator({
HomeDrawer: {screen:HomeDrawer},
WelcomeScreen: {screen:WelcomeScreen},
LoginScreen: {screen:LoginScreen},
NoteMeHome: {screen:NoteMeHome},
SettingsScreen: {screen:SettingsScreen}
})
const AppStackNavigator2 = new StackNavigator({
WelcomeScreen: {screen:WelcomeScreen},
HomeDrawer: {screen:HomeDrawer},
LoginScreen: {screen:LoginScreen},
NoteMeHome: {screen:NoteMeHome},
SettingsScreen: {screen:SettingsScreen}
})
export default HomeScreen;
Now, after running this, if I get null value in the variable getValue , then it is showing the following warning-
Warning: Can't call setState(or forceUpdate) on an unmounted
component. this is a no-op, but it indicates a memory leak in your
application. To fix, cancel all subscription and asynchronous tasks in
the componentWillUnmount method.
So, how can I solve this warning issue?
I don't know whether it's a good practice or not. The problem was- my component was initializing with empty string and I was checking for null in render function. Initializing getvalue with null or checking for empty string in render would solve this issue.
So, the change I made in my code is -
state = {
getValue: ''
}
And it removes the warning.
A better solution would be to use the SwitchNavigator from react-navigation since your navigation stacks are identical and you only want to route to the first screen based on that token.
see example
import React from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import {StackNavigator, createSwitchNavigator} from 'react-navigation';
import WelcomeScreen from './WelcomeScreen';
import LoginScreen from './components/LoginScreen';
import NoteMeHome from './components/NoteMeHome';
import HomeDrawer from './HomeDrawer/HomeDrawer';
import SettingsScreen from './components/SettingsScreen';
const AppStackNavigator = new StackNavigator({
HomeDrawer: {screen:HomeDrawer},
LoginScreen: {screen:LoginScreen},
NoteMeHome: {screen:NoteMeHome},
SettingsScreen: {screen:SettingsScreen}
});
export default createAppContainer(createSwitchNavigator(
{
LaunchScreen,
WelcomeScreen,
AppStackNavigator,
},
{
initialRouteName: 'LaunchScreen',
}
));
class LaunchScreen extends React.Component {
constructor(props) {
super(props);
this._getToken();
}
// Fetch the token from storage then navigate to the appropriate place
_getToken = async () => {
const tok = await AsyncStorage.getItem('toke');
// This will switch to the Welcome screen or main AppStack. Then this launch
// screen will be unmounted and thrown away.
this.props.navigation.navigate(tok ? 'AppStackNavigator' : 'WelcomeScreen');
};
// Render any loading content that you like here
render() {
return (
<View>
{/*...*/}
</View>
);
}
}

Render two navigators

There is a Login.js module, with this module the user can log in. If the user data is correct, then the user switches to another Secured.js module. For switching from the module to the module I use StackNavigator. In the Secured.js module, Tabs should be displayed below. For this I use TabNavigator. The problem is that when I try to render tabs, it does not work for me, because React Native says that two navigators can not be created on one page. I tried to google, but I could not find anything worthwhile, except for the advice to update React Native, saying "this is a bug of the old version" (I tried too, but it didn't help). Is there any ideas how I can fix it?
Secured.js
import React, { Component } from 'react';
import {
ScrollView,
Text,
View,
Button,
StyleSheet,
FlatList
} from 'react-native';
// Import getNews function from news.js
import { getNews } from '../screens/news';
// We'll get to this one later
import Article from '../components/Article';
import Tabs from '../screens/Tabs';
export default class Secured extends React.Component {
static navigationOptions = {
title: "Neuigkeiten",
headerTintColor: "#FF0000",
headerLeft: null,
};
constructor(props) {
super(props);
this.state = { articles: [], refreshing: true };
this.fetchNews = this.fetchNews.bind(this);
}
// Called after a component is mounted
componentDidMount() {
this.fetchNews();
}
fetchNews() {
getNews()
.then(articles => this.setState({ articles, refreshing: false }))
.catch(() => this.setState({ refreshing: false }));
}
handleRefresh() {
this.setState(
{
refreshing: true
},
() => this.fetchNews()
);
}
render() {
return (
<View>
<FlatList
data={this.state.articles}
renderItem={({ item }) => <Article article={item} />}
keyExtractor={item => item.url}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh.bind(this)}
/>
<View><Tabs /></View>
</View>
);
}
}
Tabs.js
import React, { Component } from 'react';
import { createBottomTabNavigator } from 'react-navigation';
import Secured from '../screens/Secured';
import Page1 from '../screens/Page1';
import Page2 from '../screens/Page2';
import Page3 from '../screens/Page3';
export default createBottomTabNavigator({
/// Secured: {screen:Secured,},
Page1: {screen:Page1,},
Page2: {screen:Page2,},
Page3: {screen:Page3,}
});
Firstly, it's not all happening because of react-native version is not updated. it's all about react-native navigation wrong use.
Let me explain you with two examples, one is wrong way similar with your case and second one is highly prefer, correct way to use navigators.
In React Native Navigation,
WRONG WAY
export default App extends React.Component {
render() {
/* In the root component we are rendering the app navigator */
return <AppNavigator />;
}
}
const AuthenticationNavigator = createStackNavigator({
SignIn: SignInScreen,
ForgotPassword: ForgotPasswordScreen,
});
class AuthenticationScreen extends React.Component {
render() {
return (
<AuthenticationNavigator />
);
}
}
const AppNavigator = createSwitchNavigator({
Auth: AuthenticationScreen, // This screen renders a navigator!
Home: HomeScreen,
});
In a screen inside of the navigator we are rendering another navigator You should avoid this! It will have its own navigation state and be unable To interact with any parent navigator, eg: it would not know the route "Home" exists
CORRECT & HIGHLY RECOMMENDED WAY
export default App extends React.Component {
render() {
return <AppNavigator />;
}
}
const AuthenticationNavigator = createStackNavigator({
SignIn: SignInScreen,
ForgotPassword: ForgotPasswordScreen,
});
const AppNavigator = createSwitchNavigator({
/*
* Rather than being rendered by a screen component, the
* AuthenticationNavigator is a screen component
*/
Auth: AuthenticationNavigator,
Home: HomeScreen,
});
IN YOUR CASE
import React, { Component } from 'react';
import { createBottomTabNavigator } from 'react-navigation';
import Secured from '../screens/Secured';
import Page1 from '../screens/Page1';
import Page2 from '../screens/Page2';
import Page3 from '../screens/Page3';
const Tabnav = createBottomTabNavigator({
/// Secured: {screen:Secured,},
Page1: {screen:Page1,},
Page2: {screen:Page2,},
Page3: {screen:Page3,}
});
and return the Tabnav in render function , instead of export the default. because we can't export more than one in one place.

Why importing components from other files caused "Invariant Violation: Element type is invalid" error?

I'm fairly advanced in iOS Swift language, but very new in react native framework or javascript language. I also have tried to find the right tutorial for stack navigator for hours but I can't find it. I'm currently using this tutorial to learn the basic of react native stack navigation, and would like to split the two screens into their own files. Basically, I want to mimic Swift with its AppDelegate.swift and View Controller's files. But it generates error like this:
Invariant Violation: Element type is invalid: expected a string (for
built-in components) or a class/function (for composite components)
but got: object. You likely forgot to export your component from the
file it's defined in, or you might have mixed up default and named
imports.
That was old error. The new error now:
TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate')
This error is located at:
in HomeScreen (at renderApplication.js:33)
...
Here's my current code. This has been edited according to the solutions.
App.js:
import React from 'react';
import { Button, AppRegistry } from 'react-native';
import { StackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';
export default HomeScreen;
const App = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
AppRegistry.registerComponent("TestProject", () => App);
HomeScreen.js:
import React from 'react';
import { Button } from 'react-native';
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' })
}
/>
);
}
}
ProfileScreen.js:
import React from 'react';
import { Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
export default class ProfileScreen extends React.Component {
static navigationOptions = {
title: 'Jane Profile',
};
render() {
const { navigate } = this.props.navigation;
return (
<Text>Welcome to Jane profile!</Text>
);
}
}
I would greatly appreciate any point out to any error and mistake in my code, as for now I'm completely oblivious to any problems in my code, as I'm learning this by myself. Please help. The first baby steps are always the hardest part every time I learn new language.
In this case, I'm trying to create a home screen with a button that leads to a second screen (profile) with a text in it. I'm also aware that I should be able to extract the name of the profile in the ProfileScreen which the HomeScreen sent, but I hardcoded it right now to make things simple for me to understand the solution.
Try this
import React from 'react';
import { StackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';
const App = StackNavigator({
HomeScreen: { screen: HomeScreen },
ProfileScreen: { screen: ProfileScreen },
}, {
initialRouteName: 'HomeScreen',
headerMode: 'none'
});
export default () => <App />;
The name of the route should be same not mandatory but
recommended.
Export the navigation element.
I don't even have a AppRegistry script in my project but it is still working.
If any issue comment that down below! Hope this will fix the issue
Note : This will work in react-navigation version 1.5.11
For react-navigation v2 try this code
import React from 'react';
import { createStackNavigator } from 'react-navigation';
import HomeScreen from './HomeScreen';
import ProfileScreen from './ProfileScreen';
const App = createStackNavigator({
HomeScreen: { screen: HomeScreen },
ProfileScreen: { screen: ProfileScreen },
}, {
initialRouteName: 'HomeScreen',
headerMode: 'none'
});
export default () => <App />;
Make the navigation script file global to access its props!
In react-native we don't register every component using AppRegistry.registerComponent, rather we register the parent component and parent component render child component. The changes that you need is to register the App component and export the HomeScreen and ProfileScreen.
Sample
App.js
...
const App = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
AppRegistry.registerComponent('projectName', () => App)
HomeScreen.js
...
class HomeScreen extends React.Component {
...
}
export default HomeScreen;
ProfileScreen.js
...
class ProfileScreen extends React.Component {
...
}
export default ProfileScreen;
Hope this will help!

Categories

Resources