Edit (15.12.2017)
There is now an easier way:
https://github.com/react-community/reason-react-native-scripts
After my last post about Reason it took me some time to get at it again. Learning a new language takes time. You have to get the new syntax, the semantics and the tooling. I'm more of a practical learner, even tho' I like it to read about new tech for days and days, I know I don't really get stuff till I tried it myself and things are always different from how the creators tell you.
Anyway, a few days ago I read about people trying to get Reason to work with React-Native and since React-Native is my thing at the moment, I wanted to try this out.
What
I will tell you how to get up and running with React-Native and Reason. I will use Create-React-Native-App, because using React-Native directly is a bit of a hassle. So no Mac or 75 TB Android SDK required!
Requirements: Linux and an Android or iOS device.
This should also work with MacOS.
How
First install the Node Version Manager.
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.4/install.sh | bash
Then use it to install Node.js 7 (Node 8 comes with npm 5, which doesn't work with create-react-native-app)
nvm install 7
Next step is to install the Create-React-Native-App.
npm i create-react-native-app -g
And use it to create... a React-Native app :D
create-react-native-app my-awesome-app
Some problems that could occur:
react-native-scripts
is missing, install it:
npm i react-native-scripts -D
The process that listens for file changes needs some additional configuration, so it can WATCH ALL THE FILES!
This works till you reboot your system:
sudo sysctl -w fs.inotify.max_user_instances=1024
sudo sysctl -w fs.inotify.max_user_watches=12288
Now we have a regular JavaScript based React-Native app, we can start it with npm start
and get a QR-code that we need to scan somehow.
We use our mobile device to install the Expo client.
For iOS you can get it from the App Store
For Android you can get it from Google Play
The Expo client lets you scan the QR-code and will open the app created before.
This is all fine and well, but we are here for a Reason!
Lets add some Reason code to our project.
I prefer to put my app-code into a modules
folder. So create one inside your my-awesome-app
directory and then put an app.re
in it!
The my-awesome-app/modules/app.re
should have this content:
open ReactNative;
let app = () =>
<View style=Style.(style([flex(1.), justifyContent(`center), alignItems(`center)]))>
<Text value="Reason is awesome!" />
</View>;
A simple function that returns some elements, nothing fancy.
But our app doesn't do anything with it right now, so we need to setup a tool chain for the build.
For this we need to add a few devDependencies
to our project.
npm i bs-platform reason-react bs-react-native -D
The OCaml compiler is compiled when installing this, which can take some time.
bs
stands for BuckleScript, a back-end for the OCaml compiler that we are going to use. It can compile OCaml and Reason into JavaScript. Like Babel can compile the fancy ES2015/16/17 features into old-school JavaScript.
bs-platform
requires a bsconfig.json
in your my-awesome-app
directory with some configuration to get running:
{
"name": "my-awesome-app",
"reason": {
"react-jsx": 2
},
"bsc-flags": ["-bs-super-errors"],
"bs-dependencies": ["bs-react-native", "reason-react"],
"sources": [{
"dir": "modules"
}]
}
Most important for us is the dir
and the name
.
We also need to add some scripts
to the package.json
.
"build": "bsb -make-world -clean-world",
"watch": "bsb -make-world -clean-world -w"
Since we installed bs-platform
as a devDependency
the bsb
command will be available for these scripts.
We can now compile the app.re
into an app.js
by running
npm run build
You will find it at my-awesome-app/lib/js/app.js
Create-React-Native-App expects an App.js
in your my-awesome-app
directory that exports a React component as default
, but our component is neither in the right file nor a default export. So we need to use the App.js
to connect the Reason world with the JavaScript world.
Open up my-awesome-app/App.js
and replace its content with this:
import {app} from "./lib/js/modules/app";
export default app;
Finally everything is in place.
Start the React-Native dev server with:
npm start
Scan the provided QR-code with your mobile device and the Expo client and it should show you "Reason is awesome!"
Later you can use npm run watch
instead of npm run build
while running npm start
so everything is compiled when you change something.
Bonus
If you want to use all the nice features of Reason while developing, I recommend using the Reason CLI with Visual Studio Code.
On Linux, install the CLI via npm
npm install -g https://github.com/reasonml/reason-cli/archive/beta-v-1.13.6-bin-linux.tar.gz
And then install the VSCode Reason plugin.
To get the nice auto-format with refmt you need to add "reason.formatOnSave": true
to your VSCode configuration.
Wrap Up
So getting started with Reason and React-Native isn't too hard I think. The dev-story for Linux feels a bit more clunky than on MacOS and overall React-Native is much slower on Linux than on MacOS, but that's a React-Native or maybe even a Create-React-Native-App issue.
What's missing, and expected to be missing in such a young language, are binding and/or libraries. I use glamorous-native for my styles in React-Native and it really feels like a big step back to go from writing something like:
<View backgroundColor="red" width="100%">
to writing this:
<View style=Style.(style([backgroundColor("red"), widthPct(100.)]))>
Styling is the bread and butter of a front-end dev, so I don't know if I can take it, haha, but the autocomplete is certainly nice.
For such a very young project I think it's still a phenomenal achievement and worth a try.
Also, if you need some visual help in setting up React-Native, I also made a video course on Skillshare that might help you.
Thanks to Ken Wheeler who wrote a React-Native app in Reason which I took as basis for this post.