Margarita
Krutikova
Kyrylo
Yakymenko
Agenda
- What is Reason?
- Why should we care?
- Language features
- The new ReasonReact hooks API
-
DEMO
- React components in Reason
- useState, useReducer
- Routing
- GraphQL with reason-apollo-hooks
- Stuff we've built with Reason
- Summary
a functional programming language
React bindings for ReasonML
compiles ReasonML to JavaScript
syntactic extension of
Allows writing React applications in ReasonML
"Babel" for ReasonML
Why?
-
Statically typed, functional and pragmatic
best of two worlds
Constraints
Flexibility
Guarantees
"Sweet Spot of Pragmatism"
Why?
-
Statically typed, functional and pragmatic
best of two worlds - Powered by Facebook (used in production)
Why?
-
Statically typed, functional and pragmatic
best of two worlds - Powered by Facebook
- Fun fact: Jordan Walke, the creator of React is now working on Reason
Why?
-
Statically typed, functional and pragmatic
best of two worlds - Powered by Facebook
- Fun fact: Jordan Walke, the creator of React is now working on Reason
- Expressive type system, strong type inference
- Extremely fast builds
Why?
-
Statically typed, functional and pragmatic
best of two worlds - Powered by Facebook
- Fun fact: Jordan Walke, the creator of React is now working on Reason
- Expressive type system, strong type inference
- Extremely fast builds
- Access to the whole JS ecosystem (npm)
- Incremental adoption possible
Syntax
- reminds of Javascript
let multiply = (a, b) => a * b;
let welcome = name => "Welcome, " ++ name;
let veggies = ["pumpkin", "kale", "broccoli"];
The cool stuff
-
Variants + pattern matching
type response =
| Fetching
| Error(string)
| Success(user);
Variant
switch (response) {
| Fetching => <Spinner />
| Error(err) => <Error err />
| Success(user) => <MyPages user />
}
type Response = {
error: string | null,
user: User | null,
isLoading: boolean
}
if (response.loading) {
...
}
if (response.error) {
...
}
if (response.user) {
...
}
Typescript
Pattern Matching (JS)
switch (action.type) {
case "FETCHING":
return "Fetching...";
case "ERROR":
if (action.errorCode === 401) {
return "Unauthorized!";
}
if (action.errorCode === 404) {
return "Not found!";
}
return "Unknown error...";
case "SUCCESS":
return action.data;
}
Pattern Matching (Reason)
switch (action) {
| Fetching => "Fetching..."
| Error(401) => "Unauthorized!"
| Error(404) => "Not found!"
| Error(_) => "Unknown error..."
| Success(data) => data
}
Pattern Matching (routing)
let url = ReasonReactRouter.useUrl();
switch (url.path) {
| ["cart"] => <CartPage />
| ["products", "sale"] => <CampaignPage />
| ["products", id] => <ProductPage id />
| _ => <NotFound />
};
Built-in router: ReasonReactRouter
The cool stuff
-
Variants + pattern matching
-
Option
Option
type option('a) = None | Some('a)
-
No null / undefined
-
Safe alternative to concept of nonexistent value
let maybeInt = Some(45);
let maybeUser = Some({ name: "John" });
Option
let maybeUser = Some({ name: "John" });
switch (maybeUser) {
| Some(user) => "Hello, " + user.name
| None => "Please, log in"
};
❌ Cannot read property of 'undefined',
'undefined' is not an object, null is not an object,
‘undefined’ is not a function (c) Javascript
Get the value out of it?
The cool stuff
-
Variants + pattern matching
-
Option
-
Records
Records
-
Fixed fields
-
Immutable
-
Very fast
-
Compile to arrays 🤯
Similar to JS objects, but
Records
type user = { name: string, age: int };
let john = {
name: "John",
age: 42
};
john.name = "Bob";
let bob = { ...john, name: "Bob" };
The cool stuff
-
Variants + pattern matching
-
Option
-
Records
-
Module system
Module system
-
No import necessary
-
Module name is file name
-
Compiler automatically searches for modules
-
Requirement: unique file names per project
-
Folder structure doesn't matter
Module system
import { Button } from '../../commmon/Button'
import { makePretty } from '../../../utils'
<Button text={Utils.makePretty(ugly)} />
* Button.re and Utils.re are somewhere in the project
The cool stuff
-
Variants + pattern matching
-
Option
-
Records
-
Module system
-
Built-in formater
Automatic code formatting
JS/TS: Prettier
- prettier-vscode
- prettier-eslint
- eslint-plugin-prettier
- eslint-config-prettier
- (tslint-config-prettier)
- .prettierrc
- .eslintrc
- settings.json -> prettier settings
reason-language-server
+
refmt
ReasonML
ReasonReact
- Reason bindings for React
- Allows writing React components to whole React applications in ReasonML
- Supports React hooks as of v0.7.0!
- Future of React? 🤔
DEMO
- Variants, powerful pattern matching
- Functional language, but pragmatic
(has mutation, side effects) - Expressive, proven type system with strong type inference
- Compilation speed
- Interop with other libs - use anything on npm!
- Possibility to compile to native code
- Driven by Facebook
Summary
- Hasn't reached a critical mass yet
- Still "raw"
-
Tooling not on par with JS/TS
-
Sometimes tricky to find up-to-date libraries/bindings
Disadvantages
Adoption Strategies
No need to go all in from the start
- Start with individual components
- Start with logic/functions
- Start with API decoders
Questions?
Example apps built with
ReasonReact
Hasura GraphQL
Netlify
MaterialUI
CSS-in-JS
Reason Gothenburg Meetup
ReasonReact
By Kyrylo Yakymenko
ReasonReact
- 377