Sharing text, links and images in react native apps

Sharing text, links and images in react native apps

Hey folks,

In this article, we will be creating the share feature for an app in React Native using
the following libraries -

  1. react-native-fs
  1. react-native-share

First things first !!

node --version 
v14.17.6

npm --version 
6.14.15

npx react-native -v      
10.2.2
  • Create a new React Native app using the following command -

       npx react-native init Share_Project
    
  • Remove the template code in App.js and ensure App.js looks like the following -

      import React from 'react';
      import {View} from 'react-native';
    
      const App = () => {
        return <View />;
      };
    
      export default App;
    
  • Now, let's install the required libraries -

Run the falling commands in your terminal to install the libraries -

react-native-fs

    npm i react-native-fs

react-native-share

    npm i react-native-share

Make sure the final package.json file of your app looks similar to the following code.

    {
      "name": "AwesomeProject",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "android": "react-native run-android",
        "ios": "react-native run-ios",
        "lint": "eslint .",
        "start": "react-native start",
        "test": "jest"
      },
      "dependencies": {
        "react": "18.2.0",
        "react-native": "0.71.10",
        "react-native-fs": "^2.20.0", // Added react-native-fs
        "react-native-share": "^8.2.2" // Added react-native-share
      },
      "devDependencies": {
        "@babel/core": "^7.20.0",
        "@babel/preset-env": "^7.20.0",
        "@babel/runtime": "^7.20.0",
        "@react-native-community/eslint-config": "^3.2.0",
        "@tsconfig/react-native": "^2.0.2",
        "@types/jest": "^29.2.1",
        "@types/react": "^18.0.24",
        "@types/react-test-renderer": "^18.0.0",
        "babel-jest": "^29.2.1",
        "eslint": "^8.19.0",
        "jest": "^29.2.1",
        "metro-react-native-babel-preset": "0.73.9",
        "prettier": "^2.4.1",
        "react-test-renderer": "18.2.0",
        "typescript": "4.8.4"
      },
      "jest": {
        "preset": "react-native"
      }
    }

You can refer to the docs for the React Native libraries added from this section -

  1. react-native-fs

  2. react-native-share

  • Once we are done with all libraries, let's create a simple button in the center of the screen.

On clicking this button the text will be shared on Whatsapp. If Whatsapp is not installed on the phone, available share options will be shown to the user.

Create a view and give it styles to occupy the full screen and align the items in the center of the screen.

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

    const App = () => {
      return (
        <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
          <Button title="Share Now" onPress={() => {}} />
        </View>
      );
    };

    export default App;

Create a function onSharePress that will contain the image download and sharing logic, and assign it to the onPress prop of the button.

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

    const App = () => {
      const onSharePress = () => {};

      return (
        <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
          <Button title="Share Now" onPress={onSharePress} />
        </View>
      );
    };

    export default App;

The UI will look similar to the below image.

Let's write our main logic for downloading and sharing, in the onSharePress function.

Import the libraries in App.js file

import Share from 'react-native-share';
import RNFS from 'react-native-fs';

Create variables for text, link and Url of the image to be shared.

Url of the image that will be shared -> imageUrl

Message to be shared -> Hi, pls visit my Hashnode profile

Link -> paditya26

const message = 'Hi, pls visit my Hashnode profile';
const imageUrl =
    'http://commondatastorage.googleapis.com/codeskulptor-demos/riceracer_assets/img/car_3.png';
const link = 'https://hashnode.com/@paditya26';

Create shareOptions object inside onSharePress function, which will be passed to Share.singleShare function.

  const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    }; /* Creating shareOptions object containing a messageKey
 with value `${message}\n${link}` so that the link appears right
 below the message when user shares the message on any platform. 
*/
  };

Wrap download and share logic, inside a try-catch block for error handling.

const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    };
    try {
    } catch (error) {
      console.log(error);
    }
  };

Download the image from the image link to a particular location in the app's cache memory.

react-native-fs library gives a downloadFile function that takes fromUrl and toFile as parameters to download the file from fromUrl and store it in the location specified by toFile. Here the name of the file is given as image.jpg. The downloadFile returns a promise. .then and .catch can be used with a promise to trigger logic if the code has been executed successfully or has failed.

const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    };
    try {
      RNFS.downloadFile({
        fromUrl: imageUrl,
        toFile: `${RNFS.CachesDirectoryPath}/image.jpg`,
      })
        .promise.then(() => {
        })
        .catch(err => {
          console.log(err);
        });
    } catch (error) {
      console.log(error);
    }
  };

Read the file in base64 format, from the location where it was stored using the readFile function of the react-native-fs library.

const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    };
    try {
      RNFS.downloadFile({
        fromUrl: imageUrl,
        toFile: `${RNFS.CachesDirectoryPath}/image.jpg`,
      })
        .promise.then(() => {
          RNFS.readFile(`${RNFS.CachesDirectoryPath}/image.jpg`, 'base64')
            .then(res => {
            })
            .catch(err => {
              console.log(err);
            });
        })
        .catch(err => {
          console.log(err);
        });
    } catch (error) {
      console.log(error);
    }
  };

Once we get the response res from the readFile function, set the url key of the shareOptions object to `data:image/png;base64,${res}`. This will help load the image on different sharing platforms.

Use the shareSingle function from the react-native-share library to share the message, link and image on various platforms. Pass shareOptions object inside the shareSingle function by using the spread operator (...).

Set social key inside the shareSingle functions as Share.Social.WHATSAPP. This allows the user to share the message, particularly on Whatsapp, if it is installed on the device. If Whatsapp is not installed on the device, this will automatically open other sharing options that are available on the device.

 const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    };
    try {
      RNFS.downloadFile({
        fromUrl: imageUrl,
        toFile: `${RNFS.CachesDirectoryPath}/image.jpg`,
      })
        .promise.then(() => {
          RNFS.readFile(`${RNFS.CachesDirectoryPath}/image.jpg`, 'base64')
            .then(res => {
              shareOptions.url = `data:image/png;base64,${res}`;
              Share.shareSingle({
                ...shareOptions,
                social: Share.Social.WHATSAPP,
              }).catch(err => {
                console.log(err);
              });
            })
            .catch(err => {
              console.log(err);
            });
        })
        .catch(err => {
          console.log(err);
        });
    } catch (error) {
      console.log(error);
    }
  };

The final code in App.js file would look like this.

import React from 'react';
import {Button, Image, View} from 'react-native';
import Share from 'react-native-share';
import RNFS from 'react-native-fs';

const App = () => {
  const message = 'Hi, pls visit my Hashnode profile';
  const imageUrl =
    'http://commondatastorage.googleapis.com/codeskulptor-demos/riceracer_assets/img/car_3.png';
  const link = 'https://hashnode.com/@paditya26';

  const onSharePress = () => {
    const shareOptions = {
      message: `${message}\n${link}`,
    };
    try {
      RNFS.downloadFile({
        fromUrl: imageUrl,
        toFile: `${RNFS.CachesDirectoryPath}/image.jpg`,
      })
        .promise.then(() => {
          RNFS.readFile(`${RNFS.CachesDirectoryPath}/image.jpg`, 'base64')
            .then(res => {
              shareOptions.url = `data:image/png;base64,${res}`;
              Share.shareSingle({
                ...shareOptions,
                social: Share.Social.WHATSAPP,
              }).catch(err => {
                console.log(err);
              });
            })
            .catch(err => {
              console.log(err);
            });
        })
        .catch(err => {
          console.log(err);
        });
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Button title="Share Now" onPress={onSharePress} />
    </View>
  );
};

export default App;

Important Things to Note -

  • Share.Social has multiple options available for some common sharing platforms like Share.Social.WHATSAPP, Share.Social.Twitter, etc. Depending on the use case developer needs to choose the correct option.

  • RNFS has multiple default locations to store files or images like C RNFS.CachesDirectoryPath, RNFS.DownloadDirectoryPath etc. Depending on the use case developer needs to choose the correct option.

  • Some of the features of react-native-fs, react-native-share are available only in Android or IOS.

The above video shows the demo for sharing the message on Whatsapp.

The above video shows the demo for sharing the message when Whatsapp is not installed and other sharing platforms are available.

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

Follow me on Twitter for more tech content on React Native.

Did you find this article valuable?

Support Parjanya Aditya Shukla by becoming a sponsor. Any amount is appreciated!