# @cawfree/react-native-elsewhere

> Ridiculously simple React Native thread unblocking

Latest version **1.0.28** (published 2019-09-28) · MIT license · 0 weekly downloads

## Install

```sh
npm install @cawfree/react-native-elsewhere
pnpm add @cawfree/react-native-elsewhere
yarn add @cawfree/react-native-elsewhere
bun add @cawfree/react-native-elsewhere
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; large bundle.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.28 |
| Published | 2019-09-28 |
| First published | 2019-05-21 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 143.4 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 15 |
| Author | hello@cawfree.com |
| Maintainers | cawfree |
| Keywords | thread, threading, background, ui, fast, processing, task, react, native, react-native |

## Links

- npm: https://www.npmjs.com/package/@cawfree/react-native-elsewhere
- Repository: https://github.com/Cawfree/react-native-elsewhere
- npm.io page: https://npm.io/package/@cawfree/react-native-elsewhere

## Dependencies (1)

- [htmlclean](https://npm.io/package/htmlclean.md) ^3.0.8

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.0.28 (latest) — 2019-09-28
- 1.0.27 — 2019-09-25
- 1.0.26 — 2019-09-25
- 1.0.25 — 2019-09-25
- 1.1.0 — 2019-09-25
- 1.0.24 — 2019-09-14
- 1.0.23 — 2019-09-14
- 1.0.22 — 2019-08-10
- 1.0.20 — 2019-05-30
- 1.0.19 — 2019-05-30
- 1.0.18 — 2019-05-30
- 1.0.17 — 2019-05-29
- 1.0.16 — 2019-05-29
- 1.0.15 — 2019-05-29
- 1.0.14 — 2019-05-29
- … 14 more at https://npm.io/package/@cawfree/react-native-elsewhere/versions

## README

# 🚨 Deprecation Notice
The `<Elsewhere />` component relies upon the `toString()` method to delegate native functions to a `<WebView />`, which is [not possible to achieve in conjunction with the Hermes engine](https://github.com/facebook/hermes/issues/114).

Developers are urged to migrate into [nodejs-mobile-react-native-bridge](https://github.com/cawfree/nodejs-mobile-react-native-bridge).

# react-native-elsewhere
Ridiculously simple React Native thread unblocking.

## 🚀 Getting Started
Using [npm](https://www.npmjs.com/package/@cawfree/react-native-elsewhere):
```shell
npm install --save @cawfree/react-native-elsewhere
```
Using [yarn](https://www.npmjs.com/package/@cawfree/react-native-elsewhere):
```shell
yarn add @cawfree/react-native-elsewhere
```
Yeah, no linking. 👍

## ⚙ How does it work?
By delegating stateless JavaScript computation to a [`<WebView />`](https://facebook.github.io/react-native/docs/webview), your app can maintain responsive whilst you crunch through heavy computation in the background.

```javascript
import React, {Component} from 'react';
import {WebView, Button, Platform, StyleSheet, Text, View, Alert} from 'react-native';

import Elsewhere from '@cawfree/react-native-elsewhere';

// https://gist.github.com/sqren/5083d73f184acae0c5b7
function doSomethingIntense(postMessage, { source }) {
  const now = new Date();
  let result = 0;   
  for (var i = Math.pow(10, 7); i >= 0; i--) {      
    result += Math.atan(i) * Math.tan(i);
  };
  postMessage({
    source,
    result,
    dt: new Date().getTime() - now.getTime(),
  });
}

type Props = {};
export default class App extends Component<Props> {
  state = {
    postMessage: () => null,
  }
  render() {
    const {
      postMessage,
    } = this.state;
    return (
      <View style={styles.container}>
        <Elsewhere
          WebView={WebView}
          engine={doSomethingIntense}
          onMessage={data => Alert.alert(JSON.stringify(data))}
          onPostMessage={(postMessage) => {
            this.setState({
              postMessage,
            });
          }}
        />
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <Text style={styles.instructions}>To get started, open the debug menu and enable the performance monitor so we can watch the JS frame rate.</Text>
        <Text style={styles.instructions}>It should read a steady 60fps. ⏰ </Text>
        <Text style={styles.instructions}>{'🤓'}</Text>
        <Text style={styles.instructions}>Tap the Button below to watch your frame rate plummet! 📉 </Text>
        <View
          style={{
            padding: 10,
          }}
        >
          <Button
            title="Run on JS thread"
            style={styles.button}
            onPress={() => doSomethingIntense(
              (data) => Alert.alert(JSON.stringify(data)),
              { source: 'ui' },
            )}
          />
        </View>
        <Text style={styles.instructions}>Intense, right? Now run the exact same operation inside of an Elsewhere. 📈 </Text>
        <View
          style={{
            padding: 10,
          }}
        >
          <Button
            title="Run on Elsewhere"
            style={styles.button}
            onPress={() => postMessage(
              { source: 'web' },
            )}
          />
        </View>
        <Text>See how the frame rate stays at 60? Magic. 🔮 </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  button: {
    marginBottom: 15,
  }
});
```

## 💾 Persistence
Using the `scripts` prop, it is possible to define an array of urls that you'd like to import as `<script/>`s within your JavaScript logic. Some scripts you call to may rely on localStorage for persistence between launches of your application; however for this to work successfully, your `engine` will need to be serialized to a file location so that thr browser can associate stored data with a given file `uri`.

This can be achieved using the following, which uses [`react-native-fs`](https://github.com/itinance/react-native-fs) as the file I/O utility.

```javascript
import React from 'react';
import Elsewhere from '@cawfree/react-native-elsewhere';
import fs from 'react-native-fs';

// XXX: Declare a uri where we'd like to store the evaluated
//      engine on the device file system.
const uri = `${fs.CachesDirectoryPath}/elsewhere.html`;

export default class Persisted extends React.Component {
  render() {
    return (
      <Elsewhere
        engine={engine}
        uri={uri}
        scripts={[
          // XXX: for example, you could use lokijs as a persistent database!
          'https://rawgit.com/techfort/LokiJS/master/src/lokijs.js',
          'https://rawgit.com/techfort/LokiJS/master/src/loki-indexed-adapter.js',
          // XXX: or you could make lodash available to your engine
          'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js',
        ]}
        onRequestPersist={(html, url) => {
          // XXX: You must return a Promise, which when reslved guarantees
          //      that the engine html has been saved to the requested uri.
          return fs.writeFile(
            url,
            html,
          );
        }}
      />
    );
  }
}
```

## ✌️ License
[MIT](https://opensource.org/licenses/MIT)

---
_Source: https://npm.io/package/@cawfree/react-native-elsewhere · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
