DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Parjanya Aditya Shukla for This is Learning

Posted on • Originally published at anexpertcoder.hashnode.dev

App Shortcuts in React Native : Never let your app shortcuts open any random app πŸ˜‚

Hey folks,

In this article we will be creating App Shortcuts for React Native apps as shown in the image. We will be creating this using the react-native-app-shortcuts library.

First things first !!

node --version
 v16.14.1
npm --version
 8.5.0
java --version
 openjdk 11.0.11 2021-04-20
Enter fullscreen mode Exit fullscreen mode

Create a New React Native App using the following commands -

npx react-native init [YOUR_PROJECT_NAME] --version 0.68.2
Enter fullscreen mode Exit fullscreen mode

Note - I am using 0.68 version of React Native. If you have upgraded React Native to the latest version you can create the app using the command ->

npx react-native init [YOUR_PROJECT_NAME]
Enter fullscreen mode Exit fullscreen mode

Let's install the dependencies

We will be installing navigation dependencies to support navigation between multiple screens in our app.

npm install @react-navigation/native @react-navigation/native-stack

npm install react-native-screens react-native-safe-area-context
Enter fullscreen mode Exit fullscreen mode

After the navigation dependencies we will be installing react-native-app-shortcuts library in our app.

npm i react-native-app-shortcuts
Enter fullscreen mode Exit fullscreen mode

Final package.json file should be similar to this ->

package.json

{
  "name": "RNAppShortcuts",
  "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-navigation/native": "^6.0.11",
    "@react-navigation/native-stack": "^6.7.0",
    "react": "17.0.2",
    "react-native": "0.68.2",
    "react-native-app-shortcuts": "^0.2.0",
    "react-native-safe-area-context": "^4.3.1",
    "react-native-screens": "^3.15.0"
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/runtime": "^7.18.9",
    "@react-native-community/eslint-config": "^3.1.0",
    "babel-jest": "^28.1.3",
    "eslint": "^8.21.0",
    "jest": "^28.1.3",
    "metro-react-native-babel-preset": "^0.72.0",
    "react-test-renderer": "17.0.2"
  },
  "jest": {
    "preset": "react-native"
  }
}

Enter fullscreen mode Exit fullscreen mode

Let's begin the journey of Code ->

  • Remove the template code in App.js and ensure App.js looks like the following -
App.js

import React from 'react';
import {
  StyleSheet,
  Text,
  View,
} from 'react-native';

const App = () => {

  return (
    <View>

    </View>
  );
};

const styles = StyleSheet.create({

});

export default App;
Enter fullscreen mode Exit fullscreen mode
  • Remove the styles constant and imports from 'react-native'

  • We will create a Navigation Container and a Stack Navigator that contains different screens for our app.

  • Import NavigationContainer and createNativeStackNavigator() from 'react-navigation/native' and 'react-navigation/native-stack' respectively.

import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
Enter fullscreen mode Exit fullscreen mode
  • Modify the return statement of App.js file. Return a NavigationContainer that encloses our Stack.Navigator inside which all our screens are defined along with their names and components.
return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeComponent} />
        <Stack.Screen name="Notification" component={NotificationComponent} />
        <Stack.Screen name="Chat" component={ChatComponent} />
      </Stack.Navigator>
    </NavigationContainer>
  );
Enter fullscreen mode Exit fullscreen mode
  • Next we will be defining these components namely - HomeComponent , NotificationComponent and ChatComponent.

In the same App.js file create three constants like ->

const NotificationComponent = ({navigation}) => {
  return (
    <>
      <Notification navigation={navigation} />
    </>
  );
};

const ChatComponent = ({navigation}) => {
  return (
    <>
      <Chat navigation={navigation} />
    </>
  );
};

const HomeComponent = ({navigation}) => {
  return (
    <>
      <Home navigation={navigation} />
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode
  • Import the Chat, Home, Notification screens like ->
import Notification from './src/Notification';
import Chat from './src/Chat';
import Home from './src/Home';
Enter fullscreen mode Exit fullscreen mode

At this stage your App.js would look like the following ->

App.js 

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import Notification from './src/Notification';
import Chat from './src/Chat';
import Home from './src/Home';

const Stack = createNativeStackNavigator();

const NotificationComponent = ({navigation}) => {
  return (
    <>
      <Notification navigation={navigation} />
    </>
  );
};

const ChatComponent = ({navigation}) => {
  return (
    <>
      <Chat navigation={navigation} />
    </>
  );
};

const HomeComponent = ({navigation}) => {
  return (
    <>
      <Home navigation={navigation} />
    </>
  );
};

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeComponent} />
        <Stack.Screen name="Notification" component={NotificationComponent} />
        <Stack.Screen name="Chat" component={ChatComponent} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode
  • At this stage it might be showing you errors that Home, Notification and Chat screens does not exists and hence they cannot be imported.

  • Let's fix this next.

  • Create a folder src at the level where
    App.js file is located.

  • Create 3 files inside the src folder namely -> Home.js, Notification.js and Chat.js

  • Also for icons download Notification icon and Chat icon from the respective links as .png images and add in the app project structure at the location

android/app/src/main/res/drawable
Enter fullscreen mode Exit fullscreen mode
  • Your folder structure for adding png files of Icons will be ->

Icon Folder Structure

  • Your folder structure should finally look like this ->

Final Folder Structure


Steps for creating screens Home.js, Chat.js and Notification.js

Home.js

Create a functional component named Home.js and export it as default from this file.
Make Sure each of the Screen Home.js, Chat.js and Notification.js accepts notification object as props

const Home = ({navigation}) => {
  return (
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

Create a styles constant and create homeStyle.

const styles = StyleSheet.create({
  homeStyle: {
    display: 'flex',
    flex: 1,
    justifyContent: 'center',
    alignSelf: 'center',
  },
});
Enter fullscreen mode Exit fullscreen mode

homeStyle will be assigned to the single view in the Home Screen with the flex value as 1 so that it takes the entire space.
justifyContent and alignSelf styles are used to align the Text component inside the View in the centre of the screen.

Inside the return method of Home functional component return View with styles as homeStyle which contains a Text Component as "Home Screen"

return (
    <View style={styles.homeStyle}>
      <Text>{'Home Screen'}</Text>
    </View>
  );
Enter fullscreen mode Exit fullscreen mode

Home.js at this stage will look like ->

Home.js 

import React from 'react';
import {Text, StyleSheet, View} from 'react-native';

const Home = ({navigation}) => {
  return (
    <View style={styles.homeStyle}>
      <Text>{'Home Screen'}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  homeStyle: {
    display: 'flex',
    flex: 1,
    justifyContent: 'center',
    alignSelf: 'center',
  },
});

export default Home;
Enter fullscreen mode Exit fullscreen mode

Chat.js

Similarly create a screen Chat.js with the following code ->


Chat.js 

import React from 'react';
import {StyleSheet, Text, TouchableOpacity} from 'react-native';

const Chat = ({navigation}) => {
  return (
    <TouchableOpacity
      onPress={() => {
        navigation.navigate('Notification');
      }}
      style={styles.cta1Style}>
      <Text style={styles.ctaTitleStyle}>{'Switch to Notifications'}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  cta1Style: {
    backgroundColor: 'red',
    padding: 20,
  },
  ctaTitleStyle: {
    color: 'white',
  },
});

export default Chat;
Enter fullscreen mode Exit fullscreen mode

Notification.js

Similarly create a screen Notification.js with the following code ->

import React from 'react';
import {StyleSheet, Text, TouchableOpacity} from 'react-native';

const Notification = ({navigation}) => {
  return (
    <TouchableOpacity
      onPress={() => {
        navigation.navigate('Chat');
      }}
      style={styles.cta2Style}>
      <Text style={styles.ctaTitleStyle}>{'Switch to Chat'}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  cta2Style: {
    backgroundColor: 'blue',
    padding: 20,
  },
  ctaTitleStyle: {
    color: 'white',
  },
});

export default Notification;

Enter fullscreen mode Exit fullscreen mode

And that's done... Now you might not be seeing any error if everything works perfectly...


Let's create the App Shortcuts for our app ->

  • Import RNAppShortcuts from 'react-native-app-shortcuts' in App.js file

  • Inside the App functional component before the return statement create 2 actions using RNAppShortcuts.addShortcut({})

App.js

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import Notification from './src/Notification';
import Chat from './src/Chat';
import Home from './src/Home';
import RNAppShortcuts from 'react-native-app-shortcuts';

const Stack = createNativeStackNavigator();

const NotificationComponent = ({navigation}) => {
  return (
    <>
      <Notification navigation={navigation} />
    </>
  );
};

const ChatComponent = ({navigation}) => {
  return (
    <>
      <Chat navigation={navigation} />
    </>
  );
};

const HomeComponent = ({navigation}) => {
  return (
    <>
      <Home navigation={navigation} />
    </>
  );
};

const App = () => {
  RNAppShortcuts.addShortcut({
    id: '1',
    shortLabel: 'Notify',
    longLabel: 'Open Notifications',
    iconFolderName: 'drawable',
    iconName: 'notification',
  });
  RNAppShortcuts.addShortcut({
    id: '2',
    shortLabel: 'Chat',
    longLabel: 'Open Chats',
    iconFolderName: 'drawable',
    iconName: 'chat',
  });
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeComponent} />
        <Stack.Screen name="Notification" component={NotificationComponent} />
        <Stack.Screen name="Chat" component={ChatComponent} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode
  • Now we will create handlers which will activate when one of the app shortcut is clicked.

  • In Home.js file import useEffect from React and create a useEffect() equivalent for ComponentWillMount() of class component for Home functional component.

  • Also import RNAppShortcuts from 'react-native-app-shortcuts' for defining app shortcuts handler.

  • This useEffect will be triggered every time this screen loads or mounts. Here we will define our App Shortcuts handler.

  • App Shortcuts handler is created using RNAppShortcuts.handleShortcut(id => {});

  • At this stage Home.js should look like ->

Home.js 

import React, {useEffect} from 'react';
import {Text, StyleSheet, View} from 'react-native';
import RNAppShortcuts from 'react-native-app-shortcuts';

const Home = ({navigation}) => {
  useEffect(() => {
    RNAppShortcuts.handleShortcut(id => {
      console.log(id);
      if (id === '1') {
        navigation.navigate('Notification');
      } else if (id === '2') {
        navigation.navigate('Chat');
      }
    });
  }, []);

  return (
    <View style={styles.homeStyle}>
      <Text>{'Home Screen'}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  homeStyle: {
    display: 'flex',
    flex: 1,
    justifyContent: 'center',
    alignSelf: 'center',
  },
});

export default Home;

Enter fullscreen mode Exit fullscreen mode

Important Things to Note -

  • They are multiple libraries in React Native for creating App Shortcuts.
  1. react-native-app-shortcuts

  2. react-native-quick-actions

  3. react-native-actions-shortcuts

  • Shortcuts are added using the following code which accepts parameters like id, shortLabel , longLabel, iconFolderName where the icon image is located, iconName which has some naming rules.
RNAppShortcuts.addShortcut({
    id,
    shortLabel,
    longLabel,
    iconFolderName,
    iconName,
  });
Enter fullscreen mode Exit fullscreen mode
  • Icon Images should be added in native android and iOS folders at right locations.

  • We can add all shortcuts to the app in Splash Screen or we can add app shortcuts based on which part of the app, user has explored.

  • We can remove app shortcuts using
    RNAppShortcuts.removeShortCut(id)

  • We can remove all app shortcuts using
    RNAppShortcuts.removeAllShortCuts()

  • Static app shortcuts are shortcuts that are created at the app installation time.

  • react-native-quick-actions library support static app shortcuts for IOS devices.

  • App shortcuts handler can be created using
    RNAppShortcuts.handleShortcut(id => {});

  • The handler accepts id, using which we can perform different operations on different app shortcut click.

Voohooooooo!! We have complete the project. Cheers !!

Follow me on Twitter for more tech content on ReactNative and Flutter.

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Good news! You can update to dark mode in your DEV settings.