1

I've searched how to setup a button to make the drawer action on Stackoverflow for my react-native project and followed as per answers, but still it is not working. Some answers, it simply didn't work, but sometimes it is giving error (Invariant violation error). But the sliding action for opening up the drawer is working, still I want to include button for navigation drawer. I referred this link : Add hamburger button to React Native Navigation

Here is my code, I'm sorry it is too large.

import React, { Component } from 'react';
import {
  StyleSheet,  Text,
  View,  TextInput,
  Button,  TouchableHighlight,
  TouchableOpacity,  Image,
  Alert,  ImageBackground,
  Platform,  YellowBox,
  Dimensions,  Keyboard,
  TouchableWithoutFeedback, AsyncStorage,
  ActivityIndicator, FlatList,
  ScrollView
} from 'react-native';
import { createStackNavigator, createAppContainer,createDrawerNavigator, DrawerToggle, DrawerNavigator, DrawerActions, StackNavigator } from "react-navigation";
import { Container, Content, ListItem, List } from "native-base";

class Hidden extends React.Component {
  render() {
    return null;
  }
}

const DismissKeyboard = ({ children }) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

class LoginView extends Component {
  static navigationOptions = {
    header: null,
  };


  constructor(props) {
    super(props);
    this.myTextInput1 = React.createRef();
    this.myTextInput2 = React.createRef();
    this.state = {
      email   : '',
      password: '',
    };
    let keys = ['email', 'password'];
    AsyncStorage.multiRemove(keys, (err) => {
      console.log('Local storage user info removed!');
    });
  }

  onClickListener = (viewId) => {
    Alert.alert("Help", "Contact Admin for "+viewId);
  }

  validateEmail = (email) => {
  var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
  };

  loginNext = ()=>{
    AsyncStorage.multiSet([
      ["email", this.state.email],
      ["password", this.state.password]
    ]);

    this.setState({
      email   : '',
      password: '',
    });

    this.myTextInput1.current.clear();
    this.myTextInput2.current.clear();

    Keyboard.dismiss();

    if (this.validateEmail(this.state.email)){
      this.props.navigation.navigate('profile');
    }
    else{
      Alert.alert('Warning','Enter proper email!')
    }
  }

  render() {


    return (
      <DismissKeyboard>
      <ImageBackground source={require('./zbg_app_1.jpg')} style={{width: '100%', height: '100%'}}>
      <View style={styles.container}>
        <View style={styles.inputContainer}>
          <Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/email/ultraviolet/50/3498db'}}/>
          <TextInput style={styles.inputs}
              placeholder="Email"
              keyboardType="email-address"
              underlineColorAndroid='transparent'
              onChangeText={(email) => this.setState({email})}
              ref = {this.myTextInput1}/>
        </View>

        <View style={styles.inputContainer}>
          <Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}/>
          <TextInput style={styles.inputs}
              placeholder="Password"
              secureTextEntry={true}
              underlineColorAndroid='transparent'
              onChangeText={(password) => this.setState({password})}
              ref = {this.myTextInput2}/>
        </View>

        <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={()=>{(this.state.email != '' && this.state.password != '') ?this.loginNext():Alert.alert('Warning','Empty Field(s)!')}}>
          <Text style={styles.loginText}>Login</Text>
        </TouchableHighlight>

        <TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('forgot_password')}>
            <Text>Forgot your password?</Text>
        </TouchableHighlight>


      </View>
      </ImageBackground>
      </DismissKeyboard>
    );
  }
}

class ProfileView extends Component {
  static navigationOptions = {
    headerTitle: 'Profile',
  };

  constructor(props) {
    super(props);
    this.myTextInput1 = React.createRef();
    this.state = {
      loggedEmail :'',
      loggedPassword: '',
      city:''
    }
  }

  submitNext = ()=>{

    this.myTextInput1.current.clear();

    Keyboard.dismiss();

    Alert.alert('Information',this.state.city);
    {/*AsyncStorage.setItem('city',this.state.city);

    this.setState({
      city:''
    });
    */}

  }



  render() {
    AsyncStorage.multiGet(['email', 'password']).then(data => {

      let email = data[0][1];
      let password = data[1][1];

      if (email !== null){
          this.setState({loggedEmail:email});
        }
    });
    return (

      <View style={{ flexDirection: 'column' , alignItems: 'center', justifyContent: 'center'}}>
        <View style={{ flexDirection: 'column' , marginTop: 60, alignItems: 'center', justifyContent: 'center'}}>
        <Text>{this.state.loggedEmail}</Text>

        <Button onPress={()=> this.props.navigation.navigate('login')}  title="Login Page"/>

        </View>
        {/*<View style={styles.container1}>
          <View style={styles.inputContainer}>
            <TextInput style={styles.inputs}
                placeholder="Enter city"
                underlineColorAndroid='transparent'
                onChangeText={(city) => this.setState({city})}
                ref = {this.myTextInput1}/>
          </View>


          <TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={()=>{(this.state.city != '') ?this.submitNext():Alert.alert('Warning','Empty Field(s)!')}}>
            <Text style={styles.loginText}>Submit</Text>
          </TouchableHighlight>

        </View>*/}
      </View>

    );
  }
}

class Custom_Side_Menu extends Component {

  render() {

    return (

      <View style={styles.sideMenuContainer}>

        <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2017/10/Guitar.jpg' }}
          style={styles.sideMenuProfileIcon} />

        <View style={{ width: '100%', height: 1, backgroundColor: '#e2e2e2', marginTop: 15}} />

        <View style={{width: '100%'}}>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/social.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('First') }} > First Activity </Text>

            </View>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/promotions.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('Second') }} > Second Activity </Text>

            </View>

            <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 10}}>

              <Image source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/08/outbox.jpg' }}
              style={styles.sideMenuIcon} />

              <Text style={styles.menuText} onPress={() => { this.props.navigation.navigate('Third') }} > Third Activity </Text>

            </View>


       </View>

       <View style={{ width: '100%', height: 1, backgroundColor: '#e2e2e2', marginTop: 15}} />


      </View>
    );
  }
}

class Fetch extends Component{

  constructor(props){
    super(props);
    this.state ={ isLoading: true,};

  }

  componentDidMount(){
    return fetch('http://d4abf7d9.ngrok.io/opdytat003/api/login/',
    {
      method: 'POST',
      headers:{
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },


    })
      .then((response) => response.json())
      .then((responseJson) => {

        this.setState({
          isLoading: false,
          dataSource: responseJson,
        }, function(){

        });

      })
      .catch((error) =>{
        console.error(error);
      });
  }

  render(){
    console.log(this.state.dataSource)
    if(this.state.isLoading){
      return(
        <View style={{flex: 1, padding: 20}}>
          <ActivityIndicator/>
        </View>
      )
    }

    return(
      <ScrollView style={{flex: 1, paddingTop:30}}>
        {/*<FlatList
          data={this.state.dataSource}
          renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
          keyExtractor={({id}, index) => id}
        />*/}
        <Text>API => Zelthy API:</Text>

        <Text>{JSON.stringify(this.state.dataSource.next_step)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.access_token)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.menu)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.detail)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.responsecode)}</Text>
        <Text>{JSON.stringify(this.state.dataSource.refresh_token)}</Text>
      </ScrollView>
    );
  }
}

const AppLogin = createStackNavigator({
    login: {
      screen: LoginView,
    },

},
{
    initialRouteName: "login"
}
);
const AppProfile = createStackNavigator({
    profile: {
      screen: ProfileView,
    },

},

);


const Nav = createDrawerNavigator(

{
  Home: {
    screen: AppLogin,
    navigationOptions:{
      drawerLockMode: 'locked-closed',
      drawerLabel: <Hidden />
    },

  },
  Profile: {
    screen: AppProfile
  },
  Activities: {screen: Custom_Side_Menu},
  API: {screen: Fetch},
  'Sign Out': {screen: LoginView},

},

{
  contentOptions: {
    activeTintColor: 'green',
    inactiveTintColor: 'white',

  },
  drawerPosition: 'left',
  drawerWidth: 200,
  drawerBackgroundColor: 'purple',
  initialRouteName: 'Home'
}

);

export default createAppContainer(Nav);

I've referred Github React Native issues links but it also didn't help in my case.

When I add this part of code in StackNavigator of Profile screen, I get this below output but no change on clicking.

navigationOptions: ({ navigation }) => ({
      title: 'Profile',  // Title to appear in status bar
      headerLeft: <Button title='=' onPress={ () => navigation.navigate('DrawerOpen') } />
    })

Screenshot: enter image description here

amrs-tech
  • 485
  • 2
  • 14
  • Please try to go through my code and give me a solution because the other solutions hadn't worked for me. – amrs-tech Aug 26 '19 at 09:53
  • Can you show us the error? – Jayraj Aug 26 '19 at 10:37
  • This output I got when adding a button, but no change on clicking the button – amrs-tech Aug 26 '19 at 10:52
  • 1
    Try replacing Button with TouchableOpacity. Also, first of all try logging something on console with onPress function of TouchableOpacity. If it is logging successfully only then attach navigation.navigate("xyz-screen"), also make sure that your navigation object has navigate method present in it. Sometimes this gives error because of undefined navigation object. – Jayraj Aug 26 '19 at 11:24
  • Thanks, I'll try it out, but how to check that navigate is present in navigation object or not, if it is not present how to fix it ? – amrs-tech Aug 26 '19 at 11:38
  • You can use withNavigation from 'react-navigation' and wrap it around your component, it will parse navigation object as parse and return HOC, which can be used anywhere even with redux connect like this, export default withNavigation(connect(mapStateToProps, mapDispatchToProps)(ComponentName)); Read doc carefully, it has all the information you need. Have a look at this, https://reactnavigation.org/docs/en/with-navigation.html#example – Jayraj Aug 26 '19 at 11:45
  • Sorry, I'm new to react-native so I'm not so good with redux and higher order component and all. I'll try your solution, hope it works. Thanks :) – amrs-tech Aug 26 '19 at 12:01
  • 1
    I got the problem solved, as you said `navigation.navigate('DrawerOpen')` didn't work and I tried `navigation.openDrawer()` as said from documentation and it worked. Thanks for your help @Jayraj ! – amrs-tech Aug 29 '19 at 05:29
  • Yep sure. I'll accept it, I've made some changes, please do approve it – amrs-tech Aug 29 '19 at 06:28

1 Answers1

1

https://reactnavigation.org/docs/en/drawer-navigator.html#drawernavigatorconfig

Add contentComponent in DrawerNavigatorConfig which displays actual side MenuBar and put hamburger on top-left of MenuBar if it slides from right and on top-right of MenuBar is it slides from left side of screen.

contentComponent is basically React Component, where you display list of items like Home, Profile, My orders, Logout etc, You can add your hamburger above all this options, somewhere in top corners.

In addition, Try replacing Button with TouchableOpacity. Also, first of all try logging something on console with onPress function of TouchableOpacity. If it is logging successfully only then attach navigation.navigate("xyz-screen"), also make sure that your navigation object has navigate method present in it. Sometimes this gives error because of undefined navigation object. If navigation object exist, the try using onPress = {navigation.openDrawer} instead of navigation.navigate("DrawerOpen").

amrs-tech
  • 485
  • 2
  • 14
Jayraj
  • 390
  • 4
  • 16