Sharing custom views in react native
Tags: reactnative, share, typescript
Published: 2020-02-18 14:32:32

As a react native developer, every day I find interesting features on apps I use frequently, but most of the time I'm just thinking about how could it be done and never try it;  that’s going to change today.  

Sharing on react native is relatively easy, with options like:
[Linking](https://facebook.github.io/react-native/docs/linking#openurl) _(to open apps like maps)_ or [Share](https://facebook.github.io/react-native/docs/share) _(to copy text to apps like Telegram)_.  Today I’ll be talking about [react-native-share](https://github.com/react-native-community/react-native-share), a simple but powerful library.

To make things a little bit more complicated. Let’s make a snapshot example where a thumbnail of the component is created and you can share it.   This post will focus on configuration and sharing custom views using [react-native-view-shot](https://github.com/gre/react-native-view-shot).

Btw, I'm using *`react-native: 0.61.5`*.

## Table Of Contents
  * [Adding dependencies](#dependencies)
  * [Integrating dependencies](#integrating)

<a name="dependencies"></a>
### Adding dependencies

```bash
yarn add react-native-share react-native-view-shot
cd ios && pod install && cd ../
```

<a name="integrating"></a>
### Integrating dependencies

To make things easier, I made a simple design with [react-native-papper](https://callstack.github.io/react-native-paper).
<img src="https://dev-to-uploads.s3.amazonaws.com/i/lnn9818tonv5hbu5aocj.png" alt="design" width="50%"/>


```jsx
        <Card>
          <Card.Title
            title="This is an example"
            subtitle={this.state.subtitle}
            left={props => <Avatar.Icon {...props} icon="folder" />}
          />
          <Card.Content>
            <Title>Nicer title</Title>
            <Paragraph>I like trains</Paragraph>
          </Card.Content>
          <Card.Cover source={{uri: 'https://picsum.photos/700'}} />
          <Card.Actions>
            <Button onPress={this.takeSnapshot}>Take Snapshot</Button>
          </Card.Actions>
        </Card>
```

To create a snapshot of the component, we need to wrap the views with the `ViewShot` component.

```jsx
import ViewShot from 'react-native-view-shot';
...

      <ViewShot>
        <Card>
          ...
        </Card>
      </ViewShot>
```

We need to keep the reference of the view as a member of the class, to make a snapshot manually:

```jsx
card = React.createRef<ViewShot>();
...
      <ViewShot ref={this.card}>
        ...
        <Button onPress={this.takeSnapshot}>Take Snapshot</Button>
        ...
      </ViewShot>
```
 
With the reference, we can take snapshots on demand by using `captureRef`.

```js
import ViewShot, {captureRef} from 'react-native-view-shot';

takeSnapshot = async () => {
  if (this.card.current) {
    const snapshot = await captureRef(this.card, {
      result: 'data-uri',
    });
    this.setState({
      snapshot,
    });
  }
};
```

`data-uri` means that the result of the snapshot will be encoded as base64 and returned as a raw string but including the Data URI schema.

We can display the snapshot using the react-native Image component:
```jsx
      <Image
        source={{uri: snapshot}}
        resizeMode={'contain'}
        style={styles.snapshot}
      />
``` 
<img src="https://dev-to-uploads.s3.amazonaws.com/i/em43tiwnx7nyane1y439.gif" alt="snapshot" width="50%"/>

Finally, we can share the custom component. 

```jsx
import Share from 'react-native-share';
...

shareSnapshot = () => {
  const {snapshot} = this.state;
  if (snapshot) {
    Share.open({
      url: snapshot,
    })
      .then((res: any) => {
        console.log(res);
      })
      .catch((err: any) => {
        err && console.log(err);
      });
  }
};

...

<Button
  disabled={!this.state.snapshot}
  icon="share"
  mode="contained"
  onPress={this.shareSnapshot}>
  {"Share"}
</Button>
```

And _voila_!

> Tapping the Share button will open a native Share Dialog, where the user can select the app that will receive the snapshot or cancel the sharing, because of this, you need to handle both results, successful `.then` and failure `.catch`, or you can use `async/await + try/catch` as well.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/cfw0f4hqty5n2qypuacy.gif" alt="snapshot" width="50%"/>


{% github https://github.com/Kyonru/rn-posts-and-tutorials/pull/1 %}