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?

Yakimych

@Yakimych

relogify.com

Example apps built with

ReasonReact

Hasura GraphQL

Netlify

MaterialUI

CSS-in-JS

margaretkrutikova

@rita_krutikova

podcasts.margareta.dev

Reason Gothenburg Meetup

ReasonReact

By Kyrylo Yakymenko

ReasonReact

  • 144