1.0.28 • Published 5 years ago

@cawfree/react-native-elsewhere v1.0.28

Weekly downloads
1
License
MIT
Repository
github
Last release
5 years ago

🚨 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.

Developers are urged to migrate into nodejs-mobile-react-native-bridge.

react-native-elsewhere

Ridiculously simple React Native thread unblocking.

🚀 Getting Started

Using npm:

npm install --save @cawfree/react-native-elsewhere

Using yarn:

yarn add @cawfree/react-native-elsewhere

Yeah, no linking. 👍

⚙ How does it work?

By delegating stateless JavaScript computation to a <WebView />, your app can maintain responsive whilst you crunch through heavy computation in the background.

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 as the file I/O utility.

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

1.0.28

5 years ago

1.0.27

5 years ago

1.0.26

5 years ago

1.0.25

5 years ago

1.1.0

5 years ago

1.0.24

5 years ago

1.0.23

5 years ago

1.0.22

5 years ago

1.0.20

5 years ago

1.0.19

5 years ago

1.0.18

5 years ago

1.0.17

5 years ago

1.0.16

5 years ago

1.0.15

5 years ago

1.0.14

5 years ago

1.0.13

5 years ago

1.0.12

5 years ago

1.0.11

5 years ago

1.0.10

5 years ago

1.0.9

5 years ago

1.0.8

5 years ago

1.0.7

5 years ago

1.0.6

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago