Skip to content
React plugin for NativeScript (under construction)
Branch: master
Clone or download
Latest commit a63498f Jun 17, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
github_img Nested Modal test Apr 27, 2019
notes Imitate nativescript-angular repo setup Mar 23, 2019
react-nativescript export Switch Jun 17, 2019
sample use legacy workflow again (I prefer explicit opt-in to HMR) Jun 16, 2019
.gitignore Ignore high-quality GIFs folder Apr 24, 2019
LICENSE Initial commit Mar 20, 2019
README.md Update readme Jun 16, 2019

README.md

React NativeScript

About

React plugin for NativeScript (very under construction; expect swathing refactors)

Status: The sample app is happily using the renderer, and I'm busy adding both components and internal functionality to it.

I'm always hanging out in the #react chat of the NativeScript Slack if you'd like to talk about this project.

Setup

The library is not stable yet, so I won't be publishing it to npm anytime soon. For now, you can install the latest commit of the project directly from GitHub at any time. The following instructions assume that you'll be developing in TypeScript.

# Create a project like this (or continue from an existing one)
tns create mycoolapp --tsc

# Clone this repo, or download a zip of it, placing it beside your NativeScript project.
git clone https://github.com/shirakaba/react-nativescript.git

# Your folder hierarchy should now look like:
.
├── mycoolapp
└── react-nativescript

# In the root of your NativeScript project.
npm install --save file:../react-nativescript/react-nativescript
npm install --save react
# OPTIONAL: Only required if you would like Hot Module Reloading:
npm install --save-dev "git+https://github.com/shirakaba/react-nativescript-hot-loader.git"
npm install --save-dev @types/react

# Build and run your project like so:
tns run ios --bundle --syncAllFiles --emulator

# OPTIONAL (library development only): You can also update the source library:
cd node_modules/react-nativescript
node_modules/.bin/tsc --watch

Please file an Issue if you meet any problems when following these instructions. They could well be missing something!

Examples

Hello World app

JSX/TSX is not supported in the entry file app.ts due to nativescript-dev-webpack filtering it out. It's pending me signing NativeScript's CLA (see this PR), but I need to get clearance from my company first.

Every other file in your project can be in JSX/TSX, however; just add "jsx": "react" to your tsconfig.json's compilerOptions and refer to sample/webpack.config.js (search for the character 'x'!).

Until then, you'll have to write your entry file in JS/TS. Here is how to make a <ContentView> component (a React wrapper around a NativeScript ContentView) without JSX:

(just add "jsx": "react" to your tsconfig.json's compilerOptions).

App without HMR

// In app.ts
import * as React from "react";
import * as ReactNativeScript from "react-nativescript/dist/index";
import ColdApp from "./ColdApp";

ReactNativeScript.startWithView(React.createElement(ColdApp, {}, null));
// ColdApp.ts
import * as React from "react";
import { App } from "./AppContainer.ts"

// See the testComponents directory for many examples of components.
const app = () => (<AppContainer/>);

export default app;
tns run ios --bundle --syncAllFiles --emulator

App with HMR

// In app.ts
import * as React from "react";
import * as ReactNativeScript from "react-nativescript/dist/index";
import HotApp from "./HotApp";

ReactNativeScript.startWithView(React.createElement(HotApp, {}, null));
// HotApp.ts
import { hot } from "react-nativescript-hot-loader/root";
import * as React from "react";
import { App } from "./AppContainer.ts"

// See the testComponents directory for many examples of components.
const app = () => (<AppContainer/>);

export default hot(app);
tns run ios --bundle --syncAllFiles --emulator --env.hmr

There are many complex components to test (or refer to) in sample/app/testComponents/testComponents.ts. GameLoop has some potential ;)

Navigation

A dedicated navigation/routing framework?

A dedicated navigation/routing framework is beyond the scope of this library, but I hope to make a compatibility layer (e.g. remapping <ContentView> to <View>) to allow React NativeScript to simply be plugged into existing navigation solutions in the world of React. Tell me if you find any good candidates.

I may attempt to create a first-class solution myself in time, but it would be as part of a separate project, with its own repository.

NativeScript Core navigation

NativeScript Core does have some navigation components to mirror those used by native apps, though, and I shall be supporting these.

TabView

Hub

Modals

Layouts

All layouts are supported. Here are a few samples:

DockLayout

AbsoluteLayout

FlexboxLayout

Based on the SDK example

Based on the SDK example

Based on the docs example

NativeScript Core Components

I'm working on wrapping up every component provided by NativeScript Core with a dedicated React wrapper, trying to provide the most intuitive (React-like) user experience I can manage. Proper documentation will come in time. To see how many of the core components I've implemented so far, simply refer to react-nativescript/src/components.

Why not just use React Native? 🤷‍♂️

There are great benefits to being able to use React as a renderer for NativeScript, rather than React Native.

  • NativeScript runs on the main thread, so you avoid a lot of async dances and message-pasting between threads for achieving certain things (see particularly the next point)
  • NativeScript has complete bindings to the native APIs, so you never need to write a plugin every time you just want to access/set a property on a native view
  • NativeScript projects simply build and install much more quickly than a React Native project because the codebase is leaner
  • The NativeScript codebase is far more approachable to contributors
  • This repo is written in TypeScript from the ground up (just like NativeScript), so typings will always be in sync and correct.

Contributing 🙋‍♀

Ideally get in contact via the Slack channel before starting any PRs.

I want to keep complex tooling down to a minimum to encourage easy on-boarding to contributors – at least until the project is stable.

Current state 🚦

This checklist is expanded upon in the roadmap below.

Note that 'basic support' may mean "seen to work in very specific favourable circumstances".

  • Basic child-nesting support
  • Basic text component support
  • Basic styles support (if it exists on View)
  • Props and State changes lead to re-renders 🎉
  • Support for custom components (I think these work already; will check)
  • Support for multiple children inside an instance
  • Support for Portals
  • Basic ListView support
  • Mapping event-handler props to event handlers (e.g. onTap prop maps to on("tap") for Button component)
  • Mapping React refs to native components (I've given an example in Button)
  • Support FormattedString
  • Support for context
  • Support for non-visual components (e.g. Renderless Components and Context Providers)
  • Implement CSS cascading (it 'just works' without any special handling)
  • Handling of props other than by Observer.setValue() (plenty of this in action in react-nativescript/client/NativeScriptPropertyOperations.ts)
  • JSX/TSX (working! Although has possibly broken hot-module reloading).
  • [IN PROGRESS] Create React Components for each of the NativeScript Core views (there are a few of them!)
  • [IN PROGRESS] Map the React NativeScript Components to platform-agnostic React primitives to support multi-platform apps! Lerna may become relevant here.
  • Mapping flexbox styles to FlexboxLayout components NOTE: these are based on Google's FlexboxLayout repo and not fully conformant with CSS Flexible Box Layout. I'm inclined to drop this goal for now.
  • Tests. I see that the Nativescript Vue repo has a rather advanced set of runnable tests. We could work towards something like this.

Potential for API compatibility with React Native 🏚

Never say never. See sample/app/RNTester for work towards this... 👩‍🔬👨‍🔬

You can’t perform that action at this time.