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

React inside Elm

sporto
September 15, 2017

React inside Elm

This presentation shows how we are embedding React inside Elm

sporto

September 15, 2017
Tweet

More Decks by sporto

Other Decks in Technology

Transcript

  1. R E A C T I N S I D E E L M
    S E B A S T I A N P O R T O

    View Slide

  2. 2 Y E A R S A G O
    S TA R T E D W I T H
    R E A C T

    View Slide

  3. T H I S Y E A R
    ELM

    View Slide

  4. E L M
    • Robust
    • Easy to refactor
    • Stable

    View Slide

  5. W H AT W E WA N T
    E L M
    E V E RY W H E R E

    View Slide

  6. B U T T H AT I S N O T
    H A P P E N I N G

    View Slide

  7. S E C O N D
    B E S T
    T H I N G
    Foundations in
    ELM
    Legacy
    widgets
    in React

    View Slide

  8. H O W ?

    View Slide

  9. W E B C O M P O N E N T S
    E L M A N D W E B C O M P O N E N T S - R I C H A R D F E L D M A N
    H T T P S : / / W W W. Y O U T U B E . C O M / WAT C H ? V = A R 3 TA K W E 8 O 0

    View Slide

  10. W E B C O M P O N E N T S
    - Shadow DOM
    - Html imports
    - Custom elements

    View Slide

  11. C U S T O M E L E M E N T S

    View Slide

  12. W H AT I S N E E D E D ?
    yarn add document-register-element
    Pollyfil
    https://github.com/WebReflection/document-register-element
    import "document-register-element"

    View Slide

  13. C U S T O M
    E L E M E N T S
    +
    R E A C T
    import "document-register-element"
    import r from "ramda"
    import React from "react"
    import ReactDOM from "react-dom"
    function render(ComponentClass: ReactClass) {
    return function() {
    function reducer(acc, node) {
    const merge = {
    [node.nodeName]: node.nodeValue,
    }
    return r.merge(merge, acc)
    }
    const props = r.reduce(reducer, {}, this.attributes)
    ReactDOM.render(
    , this
    )
    }
    }
    function detach() {
    ReactDOM.unmountComponentAtNode(this)
    }
    function registerCustomElement(ComponentClass: ReactClass, tagName: string) {
    const elementPrototype = Object.create(HTMLElement.prototype)
    elementPrototype.attachedCallback = render(ComponentClass)
    elementPrototype.attributeChangedCallback = render(ComponentClass)
    elementPrototype.detachedCallback = detach
    elementPrototype.createdCallback = created
    try {
    return document.registerElement(tagName || ComponentClass.displayName, {
    prototype: elementPrototype,
    })
    } catch(e) {
    rollbar.error(e)
    }
    }
    export default registerCustomElement

    View Slide

  14. R E G I S T E R A C U S T O M E L E M E N T
    function Widget(props) {
    ...
    }
    registerCustomElement(Widget, "x-widget")

    View Slide

  15. U S I N G I T
    node "x-widget" [ attribute "count" "1" ] []

    Props for react

    View Slide

  16. I T W O R K S
    Elm
    in the middle
    React
    JS
    Routing, etc

    View Slide

  17. O U R C O N C E R N S
    • Preserve React state
    • CSS
    • Events from React to Elm
    • Redux
    • Relay

    View Slide

  18. R E A C T S TAT E
    React state
    (in custom element)
    is preserved fine
    Elm doesn't
    destroy React state

    View Slide

  19. C S S
    Shadow DOM
    Just works

    View Slide

  20. E V E N T S F R O M R E A C T
    S O M E T H I N G
    H A P P E N E D
    G O T I T

    View Slide

  21. I S L I K E J Q U E RY / B A C K B O N E
    = =
    D O M E V E N T S

    View Slide

  22. E V E N T S F R O M R E A C T
    let
    customEventDecoder =
    Decode.at [ "detail" ] Decode.string
    decoder =
    Decode.map OnTriggerEvent customEventDecoder
    in
    node "x-widget"
    [ attribute "eventname" "trigger"
    , on "trigger" decoder
    ] []
    Listen to DOM events

    View Slide

  23. const event = new CustomEvent(props.eventname, {
    detail: "Hello",
    bubbles: true,
    })
    function send(e) {
    e.target.dispatchEvent(event)
    }
    return (

    Send event

    )
    E V E N T S F R O M R E A C T
    Trigger DOM events

    View Slide

  24. R E D U X
    O P E N T H E
    M E N U
    O K

    View Slide

  25. R E D U X
    const store = createStore(update)
    window.reduxStore = store
    E L M



    In custom element
    Outer layer

    View Slide

  26. PA S S I N G P R O P S
    To Elm
    via ports
    To Read
    via attrs
    Or Redux

    View Slide

  27. O T H E R
    E L M
    window is your friend
    w i n d o w . s h o w S u c c e s s = f u n c t i o n ( ) . . .
    w i n d o w . s h o w S u c c e s s ( . . . )

    View Slide

  28. N E A R F U T U R E
    Wrap all React widgets in
    custom element inside Elm

    View Slide

  29. A N D T H E N
    Swap the
    foundations

    View Slide

  30. T H A N K S

    View Slide