$30 off During Our Annual Pro Sale. View Details »

Composition on High-Order Components

Raphael Amorim
August 22, 2018
63

Composition on High-Order Components

Raphael Amorim

August 22, 2018
Tweet

Transcript

  1. Composition on
    hIGH-ORDER
    cOMPONENTS
    RAPHAEL AMORIM

    View Slide

  2. Hi, I’m Raphael.
    @raphamorims

    View Slide

  3. godaddy.com/careers

    View Slide

  4. Disclaimer.
    (You will probably not need a couple of things presented here)

    View Slide

  5. "all the cool kids are doing it."
    So why this talk?

    View Slide

  6. The goal of this talk is to present 

    Composition on React Components.

    View Slide

  7. The goal of this talk is to present 

    Composition on React Components.
    • Fast introduction to HOC
    • Composition on real world
    • Extra: Recompose library

    View Slide

  8. HOC :: Component -> Component

    View Slide

  9. class CommentList extends React.Component {

    constructor(props) {

    super(props);

    this.state = {

    comments: DataSource.getComments()

    };

    }



    render() {

    return (



    {this.state.comments.map((comment) => (



    ))}



    );

    }

    }

    View Slide

  10. class BlogPost extends React.Component {

    constructor(props) {

    super(props);

    this.state = {

    blogPost: DataSource.getBlogPost(props.id)

    };

    }

    render() {

    return ;

    }

    }

    View Slide

  11. const CommentListWithSubscription = withSubscription(

    CommentList,

    (DataSource) => DataSource.getComments()

    );

    const BlogPostWithSubscription = withSubscription(

    BlogPost,

    (DataSource, props) => DataSource.getBlogPost(props.id)

    );

    View Slide

  12. Ok Raphael, we got it.

    View Slide

  13. Where you’re planning to go with it?

    View Slide

  14. Present HOC compositions as an option

    View Slide

  15. github.com/raphamorim/react-motions

    View Slide

  16. import { Shake } from 'react-motions'
    const ComponentWithShake = () => (


    Shake your booty, shake your booty 



    )

    View Slide

  17. import { withShake } from 'react-motions'
    const ComponentWithShake = () => withShake(

    Shake your booty, shake your booty 


    )

    View Slide

  18. import { Bounce } from 'react-motions'
    const DoNotStopBouncing = () => (

    Bouncing…

    )

    View Slide

  19. import { withBounce, withInfinite } from 'react-motions'
    const DoNotStopBouncing = withInfinite(

    withBounce(

    Bouncing…

    )

    )

    View Slide

  20. import { 

    withBounce, withShake, withInfinite, withSequence 

    } from 'react-motions'
    const Component = How can I look beautiful
    const ComponentWithShake = withShake(Component)
    const ComponentWithShakeAndBounce = withShake(withBounce(Component))

    const ComponentWithInfiniteBounce = withInfinite(withBounce(Component))

    const ComponentWithShakeThenBounce = withSequence(withShake(withBounce(Component)))
    Recap

    View Slide

  21. import { 

    withBounce, withShake, withInfinite, withSequence 

    } from 'react-motions'
    const Component = How can I look beautiful
    const ComponentWithShake = withShake(Component)

    const ComponentWithShakeAndBounce = withShake(withBounce(Component))

    const ComponentWithInfiniteBounce = withInfinite(withBounce(Component))

    const ComponentWithShakeThenBounce = withSequence(withShake(withBounce(Component)))

    View Slide

  22. import { 

    withBounce, withShake, withInfinite, withSequence 

    } from 'react-motions'
    const Component = How can I look beautiful
    const ComponentWithShake = withShake(Component)

    const ComponentWithShakeAndBounce = withShake(withBounce(Component))

    const ComponentWithInfiniteBounce = withInfinite(withBounce(Component))

    const ComponentWithShakeThenBounce = withSequence(withShake(withBounce(Component)))

    View Slide

  23. import { 

    withBounce, withShake, withInfinite, withSequence 

    } from 'react-motions'
    const Component = How can I look beautiful
    const ComponentWithShake = withShake(Component)

    const ComponentWithShakeAndBounce = withShake(withBounce(Component))

    const ComponentWithInfiniteBounce = withInfinite(withBounce(Component))

    const ComponentWithShakeThenBounce = withSequence(withShake(withBounce(Component)))

    View Slide

  24. const Component = () => (
    withInfinite(
    withFadeOut(
    withInfinite(
    withShake(
    Bouncing and Fading Out infinitely!!
    )
    )
    )
    )
    )

    View Slide

  25. Extra!

    View Slide

  26. github.com/acdlite/recompose

    View Slide

  27. import { withState, enhance } from ‘recompose'


    const enhance = withState('counter', 'setCounter', 0)

    const Counter = enhance(({ counter, setCounter }) =>



    Count: {counter}

    setCounter(n => n + 1)}>Increment

    setCounter(n => n - 1)}>Decrement



    )

    View Slide

  28. import { branch, enhance, renderComponent } from ‘recompose'


    // `isLoading()` is a function that returns whether or not the component

    // is in a loading state

    const spinnerWhileLoading = isLoading =>

    branch(

    isLoading,

    renderComponent(Spinner) // `Spinner` is a React component

    )

    // Now use the `spinnerWhileLoading()` helper to add a loading spinner to any

    // base component

    const enhance = spinnerWhileLoading(

    props => !(props.title && props.author && props.content)

    )

    const Post = enhance(({ title, author, content }) =>



    {title}

    By {author.name}

    {content}



    )

    View Slide

  29. // A component that is expensive to render

    const ExpensiveComponent = ({ propA, propB }) => {...}

    // Optimized version of same component, using shallow comparison of props

    // Same effect as extending React.PureComponent

    const OptimizedComponent = pure(ExpensiveComponent)

    // Even more optimized: only updates if specific prop keys have changed

    const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)

    View Slide

  30. const enhance = compose(

    // This is a Recompose-friendly version of Relay.createContainer(), provided by recompose-relay

    createContainer({

    fragments: {

    post: () => Relay.QL`

    fragment on Post {

    title,

    content

    }

    `

    }

    }),

    flattenProp('post')

    )

    const Post = enhance(({ title, content }) =>



    {title}

    {content}



    )

    View Slide

  31. // Any Recompose module can be imported individually

    import getDisplayName from 'recompose/getDisplayName'

    ConnectedComponent.displayName = `connect(${getDisplayName(BaseComponent)})`

    // Or, even better:

    import wrapDisplayName from 'recompose/wrapDisplayName'

    ConnectedComponent.displayName = wrapDisplayName(BaseComponent, 'connect')

    import toClass from 'recompose/toClass'

    // Converts a function component to a class component, e.g. so it can be given

    // a ref. Returns class components as is.

    const ClassComponent = toClass(FunctionComponent)

    View Slide

  32. github.com/acdlite/recompose/blob/master/docs/API.md

    View Slide

  33. Thanks!

    Obrigado!

    View Slide