Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Pensar en React y Elm

Pensar en React y Elm

La única opción para escribir aplicaciones web funcionales no es usar un lenguaje de programación funcional. Podemos pensar nuestras aplicaciones web en JavaScript con un enfoque funcional e incluso introducir gradualmente un lenguaje de programación funcional a dichas aplicaciones. En esta ocasión vamos a revisar una aplicación web funcional en React y a reemplazar una parte de la aplicación con el lenguaje de programación Elm.

Elm: https://elm-lang.org
React: https://reactjs.org

Expositor invitado: Juan Pedro Villa Isaza.

Quito Lambda

April 24, 2019
Tweet

More Decks by Quito Lambda

Other Decks in Programming

Transcript

  1. Introducción – React • “A JavaScript library for building user

    interfaces” – Elm • “A delightful language for reliable web apps” • “Generate JavaScript with great performance and no runtime exceptions”
  2. Ejemplo (Contador) (React) constructor(props) { super(props); this.state = { model:

    0 }; this.decrement = this.decrement.bind(this); this.increment = this.increment.bind(this); }
  3. Ejemplo (Contador) (React) render() { return ( <div> <button onClick={this.decrement}>-</button>

    <div>{this.state.model} <button onClick={this.increment}>+</button> </div> ) }
  4. Ejemplo (Contador) (Elm) import Browser import Html exposing (Html, button,

    div, text) import Html.Events exposing (onClick)
  5. Ejemplo (Contador) (Elm) main : Program () Model Msg main

    = Browser.sandbox { init = 0 , view = view , update = update }
  6. Ejemplo (Contador) (Elm) update : Msg -> Model -> Model

    update msg model = case msg of Decrement -> model - 1 Increment -> model + 1
  7. Ejemplo (Contador) (Elm) view : Model -> Html Msg view

    model = div [] [ button [ onClick Decrement ] [ text "-" ] , div [] [ text (String.fromInt model) ] , button [ onClick Increment ] [ text "+" ] ]
  8. Ejemplo (Contador) (React) import React from "react"; import ReactDOM from

    "react-dom"; import Counter from "./Counter.jsx"; ReactDOM.render( <Counter />, document.getElementById("app") );
  9. Ejemplo (Contador) (Elm) import React from "react"; import ReactDOM from

    "react-dom"; import Elm from "react-elm-components"; import Counter from "./Counter.elm"; ReactDOM.render( <Elm src={Counter.Elm.Main} />, document.getElementById("app") );
  10. Ejemplo (TODO) (React) constructor(props) { super(props); this.state = { items:

    [], text: "" }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); }
  11. Ejemplo (TODO) (React) handleSubmit(e) { e.preventDefault(); if (!this.state.text.length) { return;

    } const newItem = { text: this.state.text, id: Date.now() }; this.setState(state => ({ items: state.items.concat(newItem), text: "" })); }
  12. Ejemplo (TODO) (React) render() { return ( <div> ... <form

    onSubmit={this.handleSubmit}> <label htmlFor="new-todo"> What needs to be done? </label> ... </form> </div> ); }
  13. Ejemplo (TODO) (React) render() { return ( <div> ... <form

    onSubmit={this.handleSubmit}> ... <input id="new-todo" onChange={this.handleChange} value={this.state.text} /> ... </form> </div> ); }
  14. Ejemplo (TODO) (React) render() { return ( <div> ... <form

    onSubmit={this.handleSubmit}> ... <button> Add #{this.state.items.length + 1} </button> </form> </div> ); }
  15. Ejemplo (TODO) (React) class TodoList extends Component { render() {

    return ( <ul> {this.props.items.map(item => ( <li key={item.id}>{item.text}</li> ))} </ul> ); } }
  16. Ejemplo (TODO) (Elm) import Browser import Html exposing (Html, button,

    div, form, h3, input, label, li, text) import Html.Attributes exposing (for, id, type_, value) import Html.Events exposing (onInput, onSubmit) import Html.Keyed exposing (ul) import Task import Time exposing (now, posixToMillis)
  17. Ejemplo (TODO) (Elm) main : Program () Model Msg main

    = Browser.element { init = init , view = view , update = update , subscriptions = always Sub.none }
  18. Ejemplo (TODO) (Elm) init : () -> (Model, Cmd Msg)

    init _ = ( { items = [] , text = "" } , Cmd.none )
  19. Ejemplo (TODO) (Elm) type alias Model = { items :

    List { id : String, text : String } , text : String }
  20. Ejemplo (TODO) (Elm) update : Msg -> Model -> (Model,

    Cmd Msg) update msg model = case msg of Add id -> ( { items = model.items ++ [{ id = id, text = model.text }] , text = "" } , Cmd.none ) ...
  21. Ejemplo (TODO) (Elm) update : Msg -> Model -> (Model,

    Cmd Msg) update msg model = case msg of ... Change text -> ( { model | text = text } , Cmd.none ) ...
  22. Ejemplo (TODO) (Elm) update : Msg -> Model -> (Model,

    Cmd Msg) update msg model = case msg of ... Submit -> ( model , if String.isEmpty model.text then Cmd.none else let toString = String.fromInt << posixToMillis in Task.perform Add (Task.map toString now) )
  23. Ejemplo (TODO) (Elm) view : Model -> Html Msg view

    model = div [] [ h3 [] [ text "TODO" ] , viewTodoList model , ... ]
  24. Ejemplo (TODO) (Elm) view : Model -> Html Msg view

    model = div [] [ ... , form [ onSubmit Submit ] [ label [ for "new-todo" ] [ text "What needs to be done?" ] , ... ] ]
  25. Ejemplo (TODO) (Elm) view : Model -> Html Msg view

    model = div [] [ ... , form [ onSubmit Submit ] [ ... , input [ id "new-todo" , value model.text , onInput Change ] [] , ... ] ]
  26. Ejemplo (TODO) (Elm) view : Model -> Html Msg view

    model = div [] [ ... , form [ onSubmit Submit ] [ ... , button [] [ text "Add #" , let n = List.length model.items in text (String.fromInt (n + 1)) ] ] ]
  27. Ejemplo (TODO) (Elm) viewTodoList : Model -> Html msg viewTodoList

    model = let viewItem item = ( item.id , li [] [ text item.text ] ) in ul [] (List.map viewItem model.items)
  28. Ejemplo (TODO) (React) import React from "react"; import ReactDOM from

    "react-dom"; import TodoApp from "./TodoApp.jsx"; ReactDOM.render( <TodoApp />, document.getElementById("app") );
  29. Ejemplo (TODO) (Elm) import React from "react"; import ReactDOM from

    "react-dom"; import Elm from "react-elm-components"; import TodoApp from "./TodoApp.elm" ReactDOM.render( <Elm src={TodoApp.Elm.Main} />, document.getElementById("app") );
  30. Ejemplo (Formulario) (React) import React, { Component } from "react";

    import Elm from "react-elm-components"; import styled from "styled-components"; import "bootstrap/dist/css/bootstrap.min.css"; import ValidatePassword from "./ValidatePassword.elm";
  31. Ejemplo (Formulario) (React) state = { displayValidation: false, oldPassword: "",

    newPassword: "", confirmNewPassword: "", ports: undefined, validation: { ok: true, msg: "" } }
  32. Ejemplo (Formulario) (React) init = ports => { ports.updateValidation.subscribe(validation =>

    { this.setState({ validation }) }); this.setState({ ports }); }
  33. Ejemplo (Formulario) (React) handleChangeNewPassword = e => { this.setState({ displayValidation:

    false, newPassword: e.target.value }); const ports = this.state.ports ports.updatePassword.send(e.target.value); }
  34. Ejemplo (Formulario) (React) handleChangeConfirmNewPassword = e => { this.setState({ displayValidation:

    false, confirmNewPassword: e.target.value }); const ports = this.state.ports; ports.updateConfirmPassword.send(e.target.value); }
  35. Ejemplo (Formulario) (React) render() { const flags = { password:

    this.state.newPassword, confirmPassword: this.state.confirmNewPassword }; return ( <Wrapper> <Elm src={ValidatePassword.Elm.Main} flags={flags} ports={this.init} /> ... </Wrapper> ); }
  36. Ejemplo (Formulario) (React) render() { ... return ( <Wrapper> ...

    <ValidationWrapper> {this.state.displayValidation && <Validation validation={this.state.validation} /> } </ValidationWrapper> ... </Wrapper> ); }
  37. Ejemplo (Formulario) (React) render() { ... return ( ... <form

    ... onSubmit={this.handleSubmit}> ... <label>... <input ... onChange={this.handleChangeNewPassword} value={this.state.newPassword} required /> ... ); }
  38. Ejemplo (Formulario) (React) const Validation = ({ validation }) =>

    { const className = validation.ok ? "alert alert- success" : "alert alert-danger"; return ( <div className={className}> {validation.msg} </div> ) }
  39. Ejemplo (Formulario) (Elm) main : Program Model Model Msg main

    = Platform.worker { init = init , update = update , subscriptions = subscriptions }
  40. Ejemplo (Formulario) (Elm) validate : Model -> { ok :

    Bool, msg : String} validate { password, confirmPassword } = if String.isEmpty password then { ok = False , msg = "Error! Password is required." } else if password /= confirmPassword then { ok = False , msg = "Error! Passwords don't match." } ...
  41. Ejemplo (Formulario) (Elm) validate : Model -> { ok :

    Bool, msg : String} validate { password, confirmPassword } = ... else if String.length password < 6 then { ok = False , msg = "Error! Password is too short." } else { ok = True , msg = "OK!" }
  42. Ejemplo (Formulario) (Elm) init : Model -> (Model, Cmd Msg)

    init model = ( model , updateValidation (validate model) )
  43. Ejemplo (Formulario) (Elm) port updateValidation : { ok : Bool,

    msg : String } -> Cmd msg port updatePassword : (String -> msg) -> Sub msg port updateConfirmPassword : (String -> msg) -> Sub msg
  44. Ejemplo (Formulario) (Elm) update : Msg -> Model -> (Model,

    Cmd Msg) update msg model = case msg of Password password -> let newModel = { model | password = password } in (newModel, updateValidation (validate newModel)) ConfirmPassword password -> let newModel = { model | confirmPassword = password } in (newModel, updateValidation (validate newModel))
  45. Ejemplo (Formulario) (Elm) subscriptions : Model -> Sub Msg subscriptions

    _ = Sub.batch [ updatePassword Password , updateConfirmPassword ConfirmPassword ]
  46. Ejemplo (Formulario) (React) import React from "react"; import ReactDOM from

    "react-dom"; import Elm from "react-elm-components"; import ChangePassword from "./ChangePassword.jsx"; ReactDOM.render( <ChangePassword />, document.getElementById("app") );
  47. Referencias – React • React • Thinking in React –

    Elm • Elm • An Introduction to Elm • Elm in Action