React native Drawer only after login - navigation-drawer

I have snack link here
https://snack.expo.io/#mparvez19861/drawer-navigation?session_id=snack-session-hyLuO4xPa
I am trying to show drawer only if user login, for login there will not be any drawer.
Please help
Thanks

You can accomplish this by wrapping your Drawer Navigator in a Switch Navigator. Upon logging in, the Switch Navigator will switch from the login screen (which is just a screen), to the main App screen (which is initialized with createDrawerNavigator).
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import {
createSwitchNavigator,
createStackNavigator,
createAppContainer,
createDrawerNavigator,
} from 'react-navigation';
class Screen extends Component {
render() {
return (
<View style={styles.container}>
<Text>Screen</Text>
</View>
);
}
}
class AuthScreen extends Component {
render() {
return (
<View style={styles.container}>
<Text>Auth Screen</Text>
<TouchableOpacity onPress={() => this.props.navigation.navigate('App')}>
<Text>Login</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
marginTop: 40,
justifyContent: 'center',
alignItems: 'center',
},
});
const SomeStackNavigator = createStackNavigator({
ScreenA: Screen,
ScreenB: Screen,
});
const AppStack = createDrawerNavigator({
StackA: {
name: 'StackA',
screen: SomeStackNavigator,
},
StackB: {
name: 'StackB',
screen: SomeStackNavigator,
},
});
const AppNavigator = createSwitchNavigator(
{
App: AppStack,
Auth: {
screen: AuthScreen,
},
},
{
initialRouteName: 'Auth',
},
);
const AppContainer = createAppContainer(AppNavigator);
export default AppContainer;
Check it out here.

Related

Image not showing in React Native Web App. Appears when I build for Android or iOS but doesn't show when using react-scripts start

I am trying to display an image in a React Native Web App which is run using react-scripts start. When I build the App for iOS or Android, the image appears perfectly fine (using expo) but when I build it for the Web App, the image fails to load. Here is the code snippet for the Home component where the image is loaded
import React from "react";
import { ScrollView, ActivityIndicator, StyleSheet, Image, ImageBackground } from "react-native";
import UserList from "./user-list";
import Header from './header';
import sanityClient from './assets/client'
import BackButton from './back-button'
import User from './user'
// import {Asset} from 'expo-asset';
// const imageURI = Asset.fromModule(require('./arrow.png')).uri;
const image = require('./assets/aoeu.jpg');
class Home extends React.Component {
state = {
user: {},
loading: true
};
componentDidMount() {
// TODO: get users
this.getUser();
}
async getUser() {
sanityClient.fetch(`*[ _type == "user" && emailAddress.current == "dwight#viamaven.com"]`)
.then((data) => {
console.log(data);
this.setState({user: data[0], loading: false});
console.log(this.state.user);
})
.catch((err) => console.error(err))
// const res = await fetch("https://randomuser.me/api/?results=20");
// const { results} = await res.json();
// // console.log(results)
// this.setState({users: [...results], loading: false});
}
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator = {false}
showHorizontalScrollIndicator = {false}
>
{this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<View>
<Header title={this.state.user.name} />
<View>
<Image
source={require('./arrow.png')}
style={styles.image}
/>
</View>
<User />
</View>
)}
</ScrollView>
);
}
}
var styles = StyleSheet.create({
container: {
backgroundColor: "white",
width: '375px',
height: '812px',
// top: '50px',
},
centering: {
alignItems: "center",
justifyContent: "center",
padding: 8,
height: '100vh'
},
image: {
width: '50px',
height: '50px',
marginRight: 20,
boxShadow: "0 1px 2px 0 rgba(0,0,0,0.1)"
}
});
export default Home;
Here is a link to the GitHub repo where the entire project is stored https://github.com/nimbusdin/stackreactnative
Try to import this way and use it like this
import image = './assets/aoeu.jpg';
<Image
source={image}
style={styles.image}
/>

React Native: Saving image URI via AsyncStorage and reloading in different React Navigation screen

I am currently trying to combine a React Native Camera example with the React Navigation v2 and want to take a picture in the first view (called CameraView), save said picture to AsyncStorage, navigate to a second view (called GalleryView) and render this picture from AsyncStorage into an image tag.
I am using RN 0.57.1, RN-Camera 1.3.1, React Navigation 2.18.0 on a Windows 10 computer emulating an Android phone running Android version 8.0.0.
This is the code for the two views:
CameraView.js:
import React from "react";
import {
AsyncStorage,
Dimensions,
StyleSheet,
TouchableHighlight,
View
} from "react-native";
import { RNCamera as Camera } from "react-native-camera";
const styles = StyleSheet.create({
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
capture: {
width: 70,
height: 70,
borderRadius: 35,
borderWidth: 5,
borderColor: "#FFF",
marginBottom: 15
}
});
class CameraView extends React.Component {
static navigationOptions = ({ navigation }) => ({
header: null
});
constructor(props) {
super(props);
this.state = {
imageUri: null
};
}
takePicture = async () => {
try {
const imageData = await this.camera.takePictureAsync({
fixOrientation: true
});
this.setState({
imageUri: imageData.uri
});
this._saveImageAsync();
} catch (err) {
console.log("err: ", err);
}
};
_saveImageAsync = async () => {
await AsyncStorage.setItem("imageUri", this.state.imageUri);
this.props.navigation.navigate("GalleryView");
};
render() {
return (
<Camera
ref={cam => {
this.camera = cam;
}}
style={styles.preview}
flashMode={Camera.Constants.FlashMode.off}
permissionDialogTitle={"Permission to use camera"}
permissionDialogMessage={
"We need your permission to use your camera phone"
}
>
<TouchableHighlight
style={styles.capture}
onPress={this.takePicture.bind(this)}
underlayColor="rgba(255, 255, 255, 0.5)"
>
<View />
</TouchableHighlight>
</Camera>
);
}
}
export default CameraView;
GalleryView.js:
import React from "react";
import {
AsyncStorage,
Button,
Dimensions,
StyleSheet,
Text,
Image,
View
} from "react-native";
const styles = StyleSheet.create({
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
cancel: {
position: "absolute",
right: 20,
top: 20,
backgroundColor: "transparent",
color: "#FFF",
fontWeight: "600",
fontSize: 17
}
});
class GalleryView extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "Seismic"
});
constructor(props) {
super(props);
AsyncStorage.getItem("imageUri").then(response => {
this.setState({
imageUri: response
});
});
}
render() {
return (
<View>
<Image source={{ uri: this.state.imageUri }} style={styles.preview} />
<Text
style={styles.cancel}
onPress={() => this.state.setState({ imageData: null })}
>
X
</Text>
<Button
title="Map View"
onPress={() => this.props.navigation.popToTop()}
/>
</View>
);
}
}
export default GalleryView;
The first-mentioned example works fine, but when trying to use the AsyncStorage I get the error below after snapping the image and executing navigate() to the second view.
TypeError: TypeError: null is not an object (evaluating
'this.state.imageUri')
This error is located at:
in GalleryView (at SceneView.js:9)
in SceneView (at StackViewLayout.js:478)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AnimatedComponent (at screens.native.js:58)
in Screen (at StackViewCard.js:42)
in Card (at createPointerEventsContainer.js:26)
in Container (at StackViewLayout.js:507)
in RCTView (at View.js:44)
in ScreenContainer (at StackViewLayout.js:401)
in RCTView (at View.js:44)
in StackViewLayout (at withOrientation.js:30)
in withOrientation (at StackView.js:49)
in RCTView (at View.js:44)
in Transitioner (at StackView.js:19)
in StackView (at createNavigator.js:57)
in Navigator (at createKeyboardAwareNavigator.js:11)
in KeyboardAwareNavigator (at createNavigationContainer.js:376)
in NavigationContainer (at routes.js:39)
in Routes (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33)
>
This error is located at:
in NavigationContainer (at routes.js:39)
in Routes (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33) render
C:\Users\msteinbrink\Safeguard\seismic-app\src\screens\GalleryView.js:25:11
proxiedMethod
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-proxy\modules\createPrototypeProxy.js:44:35
finishClassComponent
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:10563:21
updateClassComponent
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:10505:4
beginWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:11338:8
performUnitOfWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14091:21
workLoop
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14129:41
renderRoot
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14226:15
performWorkOnRoot
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15193:17
performWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15090:24
performSyncWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:15047:14
requestWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14925:19
scheduleWork
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:14711:16
enqueueSetState
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Renderer\oss\ReactNativeRenderer-dev.js:7700:17
setState
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react\cjs\react.development.js:372:31
dispatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-navigation\src\createNavigationContainer.js:342:22
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-navigation\src\getChildNavigation.js:56:33
_callee2$
C:\Users\msteinbrink\Safeguard\seismic-app\src\screens\CameraView.js:88:16
tryCatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:62:44
invoke
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:288:30
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:114:28
tryCatch
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:62:44
invoke
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:152:28
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\#babel\runtime\node_modules\regenerator-runtime\runtime.js:162:19
tryCallOne
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\promise\setimmediate\core.js:37:14
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\promise\setimmediate\core.js:123:25
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:295:23
_callTimer
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:152:14
_callImmediatesPass
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:200:17
callImmediates
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\Core\Timers\JSTimers.js:464:30
__callImmediates
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:320:6
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:135:6
__guard
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:297:10
flushedQueue
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:17
invokeCallbackAndReturnFlushedQueue
C:\Users\msteinbrink\Safeguard\seismic-app\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:130:11
I would appreciate if someone could point out how to properly use AsyncStorage with React Navigation to render a previously saved image from React Native Camera. As you probably could tell, I am fairly new to React Native, so please tell me if I got the concept completely wrong or anything.
Thanks in advance!
Thanks to Wainages comment, I made it work. I added the state isLoaded in GalleryView and show just the text "Loading" before the async operation is done.
import React from "react";
import {
AsyncStorage,
Dimensions,
StyleSheet,
Text,
Button,
Image,
View
} from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#000000"
},
preview: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width
},
cancel: {
position: "absolute",
right: 20,
top: 20,
backgroundColor: "transparent",
color: "#FFF",
fontWeight: "600",
fontSize: 17
}
});
class GalleryView extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "Seismic"
});
constructor(props) {
super(props);
this.state = {
imageUri: null,
isLoaded: false
};
AsyncStorage.getItem("imageUri").then(response => {
this.setState({
isLoaded: true,
imageUri: response
});
});
}
renderImage() {
return (
<View>
<Image source={{ uri: this.state.imageUri }} style={styles.preview} />
<Text
style={styles.cancel}
onPress={() => this.setState({ path: null })}
>
X
</Text>
</View>
);
}
renderLoadingScreen() {
return (
<View>
<Text style={styles.cancel}>Loading</Text>
<Button
title="Map View"
onPress={() => this.props.navigation.popToTop()}
/>
</View>
);
}
render() {
return (
<View style={styles.container}>
{this.state.isLoaded ? this.renderImage() : this.renderLoadingScreen()}
</View>
);
}
}
export default GalleryView;

Changing screen gives undefined props.navigation error react native

I am trying to change screen after few seconds which is for splash screen effect in react native. I have a main screen in which app originates. The code for first screen is:
import HomeUp from './HomeUp'
import Splash from './Splash'
import React, { Component } from "react";
export default class OriginPage extends Component {
constructor(props){
super(props)
this.state = {
component : <Splash />
}
}
componentDidMount(){
// Start counting when the page is loaded
this.timeoutHandle = setTimeout(()=>{
// Add your logic for the transition
this.setState({ component: <HomeUp /> })
}, 5000);
}
componentWillUnmount(){
clearTimeout(this.timeoutHandle);
}
render() {
return (
this.state.component
);
}
}
My splash screen is :
import React from 'react';
import { StatusBar , View , Text , ActivityIndicator } from 'react-native';
export default class Splash extends React.Component {
render() {
return (
<View style={{ flex: 1 , justifyContent: 'center' , alignItems: 'center' , backgroundColor : '#34495e'}}>
<StatusBar backgroundColor="#2c3e50" barStyle="light-content"/>
<Text style={{ color : 'white',fontSize : 18 }}>Hello Splash</Text>
<ActivityIndicator color={'white'}/>
</View>
)
}
}
Till now everything works fine and the screen change over after 5s also working but this below code has bug.
import React, { Component } from "react";
class HomeUp extends Component {
render () {
const { navigate } = this.props.navigation;
return(
<TouchableHighlight onPress={() => navigate("Products", { product: item })} underlayColor="transparent">
<View style={styles.view} >
<Image style={styles.image} source={{uri: item.images[0].src}} />
<Text style={styles.name}>{item.name}</Text>
</View>
</TouchableHighlight>
);
}
}
Loading this screen alone have no bug but while changing screen I get undefined navigation.props error. hanks in adavanced.
If you are deconstructing your navigation props in your HomeUp component you should do it as follows:
const { navigation } = this.props;
Or also:
const navigate = this.props.navigation;
Hope it helps.

react-navigation - drawer navigation inside stack navigation in react native

Image of my codes, image of error
Managed to build my first React native-navigation v2, a stack navigation from LoginScreen to HomeScreen.
The problem I have is that I tried putting a Drawer Navigation on the HomeScreen and placing it inside the stack navigation but I can't understand the way to do it.
error message: Unable to resolve ./src/components/HomeScreen" from ".//src/components/DrawerNavigator.js: The module./src/components/HomeScreen` could not be found"
Failed building JavaScript bundle
Take a look at my code below.
LoginForm.js
import React, {Component} from 'react';
import {StyleSheet, View, TextInput, TouchableOpacity, Text, StatusBar} from 'react-native';
export default class LoginForm extends Component {
render() {
return (
<View style={styles.container}>
<StatusBar
barStyle="dark-content"
/>
<TouchableOpacity style={styles.buttonContainer} onPress={() => this.props.navigation.navigate('DrawerNavigator')}>
<Text style={styles.buttonText}>LOGIN</Text>
</TouchableOpacity>
</View>
);
}
}
App.js
import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';
import { Header, List, ListItem, Icon } from 'react-native-elements';
import Login from './src/components/Login/Login';
import LoginForm from './src/components/Login/LoginForm';
import HomeScreen from './src/components/HomeScreen';
import DayPlanScreen from './src/components/DayPlanScreen';
import { createStackNavigator } from 'react-navigation';
import DrawerNavigator from './src/components/DrawerNavigator'
export default class App extends React.Component {
static navigationOptions = {
header: null
}
render() {
return (
<View style={styles.container}>
{
<AppStackNavigator />
}
</View>
);
}
}
const AppStackNavigator = createStackNavigator ({
Login: Login,
Home: HomeScreen,
DrawerNavigator: DrawerNavigator
})
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#fff',
},
addBtn: {
position: 'absolute',
bottom: 10,
right: 0
},
});
DrawerNavigator.js
import React, { Component } from "react";
import {
View,
Text,
StyleSheet
} from "react-native";
import HomeScreen from './src/components/HomeScreen';
import { createDrawerNavigator } from 'react-navigation'
const DrawerNavigator = createDrawerNavigator({
Home: HomeScreen,
DayPlan: DayPlanScreen
})
export default DrawerNavigator;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
HomeScreen
import React, { Component } from "react";
import {
View,
Text,
StyleSheet
} from "react-native";
import { Button } from 'react-native-elements';
class HomeScreen extends Component {
render(){
return (
<View style={styles.container}>
<Text style={{color: 'white'}}>HomeScreen</Text>
<Button
title='LOGIN SCREEN'
onPress={()=>this.props.navigation.goBack()}
fontWeight='700'
backgroundColor='#3AD7FF'
color='#424242'
/>
</View>
);
}
}
export default HomeScreen;
const styles = StyleSheet.create({
container:{
flex:1,
alignItems:'center',
justifyContent:'center',
backgroundColor: '#424242'
}
});

Nesting Stack Navigator with Drawer Navigator

I am trying to have stack navigation along with drawer navigation. Basically I want the drawer to be in only one scene all time. I have tried to do so but nothing occurs. I am not being able to understand what I am doing wrong.
P.S: I am new to react-native.
ConversationListScreen.js
import React, { Component } from 'react';
import {
View,
Text,
Button,
TouchableNativeFeedback,
Alert,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import styles from './styles';
export default class ConversationListScreen extends Component
{
static navigationOptions = {
title: 'Hola',
headerLeft: (
<TouchableNativeFeedback onPress={() => Alert.alert('Hi!', 'I am a hamburger.')}>
<View style={styles.toolBackground}>
<Icon name="menu" style={ styles.menuIcon }/>
</View>
</TouchableNativeFeedback>
),
headerRight: (
<TouchableNativeFeedback onPress={() => Alert.alert('Hi!', 'What you want to search?')}>
<View style={styles.toolBackground}>
<Icon name="search" style={ styles.searchIcon }/>
</View>
</TouchableNativeFeedback>
)
};
render() {
return (
<View>
</View>
);
}
}
Drawer.js
import React, { Component } from 'react';
import {
View,
Text,
} from 'react-native';
export default class SideNav extends Component
{
render() {
return (
<View>
<Text>My first Drawer</Text>
</View>
);
}
}
RouteConfig.js
import { StackNavigator, DrawerNavigator } from 'react-navigation';
import ConversationListScreen from './ConversationListScreen';
import Drawer from './Drawer';
import ChatScreen from './ChatScreen';
export const SideNav = DrawerNavigator({
Drawer: { screen: Drawer},
});
export const Hola = StackNavigator({
ConversationList: { screen: ConversationListScreen },
Drawer: { screen: SideNav },
Chat: { screen: ChatScreen },
});
I had a similar issue and what I ended up doing was using this drawer component and wrapping it around the component you want to access it with. For example if you want to access it only from ConversationListScreen you export it as <Drawer><ConversationListScreen></Drawer>
I guess you can't use drawer navigator in stack navigator as a scene. you should import SideNav in the component you want to use and try to render it as a component
Here is a workaround. We have two screens in HomeScreenNavigator which is a stackNavigator. in firstScreen we have a link to secondScreen. in secondScreen we have drawerNavigator which has a screen named ComponentWidthDrawer. this component has a button to open drawer. I tested it and it's working.
class FirstComponent extends Component{
render () {
return (
<View>
<TouchableOpacity onPress={() =>
this.props.navigation.navigate("SecondScreen")}>
<Text>Go to Second Component</Text>
</TouchableOpacity>
</View>
)
}
}
class ComponentWidthDrawer extends Component{
render () {
return (
<View>
<TouchableOpacity onPress={() => this.props.navigation.navigate("DrawerOpen")}>
<Text>Open Menu</Text>
</TouchableOpacity>
</View>
)
}
}
const SecondComponent = DrawerNavigator({
Drawer: {
screen: ComponentWidthDrawer,
navigationOptions: {
drawerLabel: 'Videos'
},
}
})
const HomeScreenNavigator = StackNavigator(
{
FirstScreen : {
screen: FirstComponent,
navigationOptions:{
header: false
}
},
SecondScreen: {
screen: SecondComponent,
navigationOptions:{
header: false
}
}
}
);

Resources