loading...

Custom Navigation Drawer and Sharing State From Drawer (with useContext)

technoplato profile image Michael Lustig - halfjew22@gmail.com ・3 min read

FOLLOW ME: YouTube | dev.to | Twitter | Github | Medium | Reddit

Video


React Navigation Custom Navigation Drawer and Sharing State (with useContext)

Brief Intro

Repo | Reddit Post

This is just a quick tutorial on how to create a custom drawer and then toggle some global state within that drawer that all of your components can listen to. It's also got some explanations of hooks in there, so please let me know if you have any questions on hooks.

Inspired by cool reddit.com/r/reactnative post: https://www.reddit.com/r/reactnative/comments/dcok40/passing_variables_between_a_drawer_and_a_screen/

SHUTUP, WHERES THE CODE

App.js

import React, {useState, createContext, useContext} from 'react';
import {StyleSheet, View, Text, StatusBar} from 'react-native';

import {Colors} from 'react-native/Libraries/NewAppScreen';
import {createDrawerNavigator} from 'react-navigation-drawer';
import {createAppContainer} from 'react-navigation';
import {DrawerNavigatorItems} from 'react-navigation-drawer';

const BlueContext = createContext(true);

const HomeScreen = ({navigation}) => {
  const {blue, setBlue} = useContext(BlueContext);
  const bg = blue ? 'blue' : 'red';

  return (
    <>
      <StatusBar barStyle="light-content" />
      <View style={[styles.body, {backgroundColor: bg}]}>
        <Text
          onPress={() => {
            navigation.openDrawer();
          }}
          style={styles.sectionTitle}>
          Open Drawer
        </Text>
        <Text style={styles.sectionDescription}>
          Click <Text style={styles.highlight}>Open Drawer</Text> and click the
          button to change the color. Then come back here and check it out!
        </Text>

        <Text
          onPress={() => {
            setBlue(!blue);
          }}
          style={{fontSize: 22, color: 'white'}}>
          Click me to toggle my color
        </Text>
      </View>
    </>
  );
};

const CustomDrawer = props => {
  const {blue, setBlue} = useContext(BlueContext);
  const textColor = blue ? 'blue' : 'red';
  return (
    <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
      <Text style={{fontSize: 32}}>Drawer</Text>
      <Text
        onPress={() => {
          setBlue(!blue);
        }}
        style={{fontSize: 22, color: textColor}}>
        Click me to toggle my color
      </Text>
      <DrawerNavigatorItems {...props} />
    </View>
  );
};

const DrawerNavigation = createDrawerNavigator(
  {
    Home: HomeScreen,
  },
  {
    contentComponent: CustomDrawer,
  },
);

const ApplicationContainer = createAppContainer(DrawerNavigation);

export default () => {
  const [blue, setBlue] = useState(true);
  return (
    <BlueContext.Provider value={{blue, setBlue}}>
      <ApplicationContainer />
    </BlueContext.Provider>
  );
};


const styles = StyleSheet.create({
  body: {
    flex: 1,
    backgroundColor: Colors.black,
    justifyContent: 'center',
    padding: 16,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.white,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.white,
  },
  highlight: {
    fontWeight: '700',
  },
});

package.json

{  
  "name": "ShareDrawerState",  
  "version": "0.0.1",  
  "private": true,  
  "scripts": {  
    "android": "react-native run-android",  
  "ios": "react-native run-ios",  
  "start": "react-native start",  
  "test": "jest",  
  "lint": "eslint ."  
  },  
  "dependencies": {  
    "react": "16.9.0",  
  "react-native": "0.61.2",  
  "react-native-gesture-handler": "1.4.1",  
  "react-native-reanimated": "1.3.0",  
  "react-native-screens": "2.0.0-alpha.3",  
  "react-navigation": "4.0.10",  
  "react-navigation-drawer": "2.2.2"  
  },  
  "devDependencies": {  
    "@babel/core": "7.6.2",  
  "@babel/runtime": "7.6.2",  
  "@react-native-community/eslint-config": "0.0.5",  
  "babel-jest": "24.9.0",  
  "eslint": "6.5.1",  
  "jest": "24.9.0",  
  "metro-react-native-babel-preset": "0.56.0",  
  "react-test-renderer": "16.9.0"  
  },  
  "jest": {  
    "preset": "react-native"  
  }  
}

πŸ€ŸπŸ™ THANKS FOR READING πŸ€ŸπŸ™

If you liked the post, please be sure to give it a thumbs up, a heart, an upvote, a retweet, or whatever it is that the cool kids do these days. All my follow links are below if you're intersted in quick tutorials and explanations like this one.

πŸ€” QUESTIONS | πŸ“ COMMENTS | πŸ“‰ CONCERNS | πŸ“© SUGGESTIONS

Let me know if you have any questions in the comments or if I could have done a better job explaining anything anywhere.

πŸ“ COMMENTS

Why didn't you just use setParams?

2019-09-27 12-09-15 2019-09-27 12_17_22

I was expecting setParams to work, but apparently, you can't use setParams from your root navigator. I suppose I could have nested the Drawer Navigator, but I don't really like unnecessarily cluttering things up to fix errors. Any suggestions?


Most importantly,
πŸ’»πŸ“²πŸ‘¨πŸ»β€πŸ’»KEEP CODING, KEEP LEARNING, AND KEEP DOING!

πŸ‘‡πŸ‘‡πŸ‘‡ FOLLOW ME πŸ‘‡πŸ‘‡πŸ‘‡

YouTube | dev.to | Twitter | Github | Medium | Reddit

Discussion

markdown guide
 

This example is great! Thank you so much for making it available. I'm using react-navigation for the first time and it is hard to find working example of the Drawer Navigation/side menu that uses react-navigation v4, Context is the icing on the cake!

 

I’m really glad it helped! Make sure to follow for much more of all kinds of content coming soon. I’ve been building a tool to help me go much faster and it’s just about ready for testing.

Stay tuned!