App Shortcuts in React Native : Never let your app shortcuts open any random app 😂
Tags: reactnative, react, javascript, webdev
Published: 2022-08-05 08:34:00

Hey folks, 

<img width="100%" style="width:100%" src="https://media.giphy.com/media/nfl59PMPNLKuK8v5LT/giphy.gif">

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
``` 
### Create a New React Native App using the following commands - 
```
npx react-native init [YOUR_PROJECT_NAME] --version 0.68.2
``` 

**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]
``` 





### Let's install the dependencies

<img width="100%" style="width:100%" src="https://media.giphy.com/media/hL9q5k9dk9l0wGd4e0/giphy.gif">


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
``` 

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

```
npm i react-native-app-shortcuts
``` 


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"
  }
}

``` 
### 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;
```

- 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';
``` 

- 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>
  );
``` 

- 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} />
    </>
  );
};
``` 

- Import the Chat, Home, Notification screens like -> 

```
import Notification from './src/Notification';
import Chat from './src/Chat';
import Home from './src/Home';
``` 

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;

``` 

- 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](https://icons8.com/icon/110472/notification) and [Chat icon](https://icons8.com/icon/13724/chat) from the respective links as .png images and add in the app project structure at the location 
```
android/app/src/main/res/drawable
``` 
- Your folder structure for adding png files of Icons will be -> 

![Icon Folder Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0g341xa9aajzsric5jgz.png)

- Your folder structure should finally look like this -> 


![Final Folder Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2z1obqq6ykje71macbw.png)

---


### 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;
``` 


> Create a **styles** constant and create homeStyle.

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

> 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>
  );
``` 
`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;
```
---

### 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;
``` 

---


### 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;

``` 

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;

``` 

- 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;

``` 

---


## Important Things to Note -

- They are multiple libraries in React Native for creating App Shortcuts. 


1. [**react-native-app-shortcuts**](https://www.npmjs.com/package/react-native-app-shortcuts)

2. [**react-native-quick-actions**](https://www.npmjs.com/package/react-native-quick-actions)

3. [**react-native-actions-shortcuts**](https://www.npmjs.com/package/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,
  });
```
- 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](https://twitter.com/AdityaParjanya) for more tech content on ReactNative and Flutter.