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

React Alicante 17' - Writing highly reusable React components

Javier Velasco
October 06, 2017
190

React Alicante 17' - Writing highly reusable React components

Javier Velasco

October 06, 2017
Tweet

Transcript

  1. September 2017
    Writing highly reusable
    React components
    Javi Velasco

    View Slide

  2. Thanks to our sponsors!

    View Slide

  3. javi velasco
    @javivelasco
    audiense

    View Slide

  4. A library of React components implementing Material
    Design guidelines with the power of CSS modules.
    www.react-toolbox.com
    React Toolbox

    View Slide

  5. View Slide

  6. abuse of rendering based on props collections
    “forces” you to a no-that-easy setup with webpack
    customization api based on css modules
    |> some relevant issues

    View Slide

  7. View Slide

  8. theming and customization
    what do we understand?

    View Slide

  9. “let’s change the color scheme so all
    components have a different primary color”
    |> you predict what’s going to be changed
    theming

    View Slide

  10. “the card title is too small and I don’t care
    about what md says , I want it bigger”
    |> you can’t predict what’s going to change
    style customization

    View Slide

  11. “I the date picker but I want to change the
    weekday titles from capital letters to
    their full names”
    |> you can’t make everything customizable via declarative api
    render customization

    View Slide

  12. theming + style customization + render
    customization
    |> taking customization to the limits, adapt to nearly anything
    fully flexible component
    + +

    View Slide

  13. how react faces styling
    or how can we deal with styles in react components.

    View Slide

  14. component(state) => view
    javascript
    css
    css
    linked through
    classnames

    View Slide

  15. to get theming you need building and setup
    what if we consider style a function of state?
    can we handle css as react does with html?
    |> css is not a first class citizen in react

    View Slide

  16. |>css in js
    enforcing hate and the js fatigue since 2015 ®
    my favorite: styled components
    |> css-in-js: let’s the building

    View Slide

  17. import styled, { css } from 'styled-components';
    const Button = styled.a`
    display: inline-block;
    border-radius: 3px;
    padding: 0.5rem 0;
    margin: 0.5rem 1rem;
    width: 11rem;
    background: transparent;
    color: white;
    border: 2px solid white;
    ${props => props.primary && css`
    background: white;
    color: palevioletred;
    `}
    `;
    |> simple button with styled-components

    View Slide

  18. import styled, { css } from 'styled-components';
    const Button = styled.a`
    display: inline-block;
    border-radius: 3px;
    padding: 0.5rem 0;
    margin: 0.5rem 1rem;
    width: 11rem;
    background: transparent;
    color: white;
    border: 2px solid white;
    ${props => props.primary && css`
    background: white;
    color: palevioletred;
    `}
    `;
    |> simple button with styled-components

    View Slide

  19. import styled, { css } from 'styled-components';
    const Button = styled.a`
    display: inline-block;
    border-radius: 3px;
    padding: 0.5rem 0;
    margin: 0.5rem 1rem;
    width: 11rem;
    background: transparent;
    color: white;
    border: 2px solid white;
    ${props => props.primary && css`
    background: white;
    color: palevioletred;
    `}
    `;
    |> simple button with styled-components

    View Slide

  20. import styled, { css } from 'styled-components';
    const Button = styled.a`
    display: inline-block;
    border-radius: 3px;
    padding: 0.5rem 0;
    margin: 0.5rem 1rem;
    width: 11rem;
    background: transparent;
    color: white;
    border: 2px solid white;
    ${props => props.primary && css`
    background: white;
    color: palevioletred;
    `}
    `;
    |> simple button with styled-components

    View Slide

  21. render(

    Button primitive!

    );
    |> using styled-components as primitives

    View Slide

  22. |> using styled-components as primitives
    styles are bundled with the component.
    you map state to properties (feels natural).
    the library can define an api for theming.
    overriding styles relies on javascript and the lib.

    View Slide

  23. const Button = ({ children, primary, ...other }) => (
    className={primary
    ? 'btn primary’
    : 'btn'}
    {…other}
    >
    {children}

    );
    |> using react elements as primitives

    View Slide

  24. const Button = ({ children, primary, ...other }) => (
    className={primary
    ? 'btn primary’
    : 'btn'}
    {…other}
    >
    {children}

    );
    |> using react elements as primitives

    View Slide

  25. |> using react elements as primitives
    style is not bundled but linked by using classnames.
    you map state to a combination of classnames.
    no built-in strategy to get theming.
    overriding styles relies into selector priority.

    View Slide

  26. solving theming and style customization
    using but you can use anything else!

    View Slide

  27. const Button = styled.button`
    border: 2px solid ${props => props.theme.main};
    border-radius: 3px;
    color: ${props => props.theme.main};
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    `;
    |>theming with styled-components

    View Slide

  28. const Button = styled.button`
    border: 2px solid ${props => props.theme.main};
    border-radius: 3px;
    color: ${props => props.theme.main};
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    `;
    |>theming with styled-components

    View Slide

  29. const theme = { main: 'mediumseagreen' };
    render(

    Themed

    )
    |>theming with styled-components

    View Slide

  30. const theme = { main: 'mediumseagreen' };
    render(

    Themed

    )
    |>theming with styled-components

    View Slide

  31. const Button = styled.button`
    border-radius: 3px;
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    ${props => props.styles};
    `;
    |> style customization with styled-components

    View Slide

  32. const Button = styled.button`
    border-radius: 3px;
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    ${props => props.styles};
    `;
    |> style customization with styled-components

    View Slide

  33. const styles = css`
    color: black;
    border-radius: 50%;
    background-color: ${props => (
    props.primary
    ? ‘aliceblue’
    : undefined
    )};
    `
    |>style customization with styled-components

    View Slide

  34. const styles = css`
    color: black;
    border-radius: 50%;
    background-color: ${props => (
    props.primary
    ? ‘aliceblue’
    : undefined
    )};
    `
    |>style customization with styled-components

    View Slide

  35. render(

    Customized button

    );
    |>style customization with styled-components

    View Slide

  36. const Counter = ({ children, styles }) => (


    {children}


    );
    |>style customization with styled-components

    View Slide

  37. const myCounter = {
    Wrapper: css`
    background: gray;
    border: 1px solid darkgray;
    `,
    Count: css`
    color: red;
    text-decoration: underline;
    `
    };
    |>style customization with styled-components

    View Slide

  38. render(

    4815162342

    );
    |>style customization with styled-components

    View Slide

  39. solving render customization
    introducing component injection

    View Slide

  40. import Wrapper from ‘./Wrapper’;
    import Counter from ‘./Counter’;
    const Counter = ({ children, styles }) => (


    {children}


    );
    |>back to the previous example

    View Slide

  41. const getCounter = ({ Wrapper, Count }) => (
    ({ children, styles }) => (


    {children}


    )
    );
    |>extract the node components removing the imports

    View Slide

  42. import styled from ‘styled-components’;
    const Counter = getCounter({
    Wrapper: styled.div`
    background-color: purple;
    height: 100px;
    width: 100px;
    ${props => props.styles};
    `,
    Count: styled.span`
    color: white;
    display: block;
    text-align: center;
    ${props => props.styles};
    `
    })
    |> create a counter component by injecting fela components

    View Slide

  43. import { createComponent } from ‘react-fela’;
    const Counter = getCounter({
    Wrapper: createComponent(props => {
    backgroundColor: purple,
    height: 100,
    width: 100,
    …props.styles,
    }, ‘div’),
    Count: createComponent(props => {
    alignContent: center,
    color: ‘white’,
    flex: 1,
    …props.styles,
    }, ‘span’),
    })
    |> create a counter component by injecting fela components

    View Slide

  44. import styled from ‘styled-components/native’;
    const Counter = getCounter({
    Wrapper: styled.View`
    background-color: #000;
    height: 100;
    width: 100;
    ${props => props.styles};
    `,
    Count: styled.Text`
    align-content: center;
    color: white;
    flex: 1;
    ${props => props.styles};
    `
    })
    |> create a counter component by injecting fela components

    View Slide

  45. |>
    what if I want to have a red background when
    count value is higher than 10?

    View Slide

  46. const getCounter = ({ Wrapper, Count, passthrough }) => (
    ({ children, styles }) => (
    styles={styles.Wrapper}
    {…passthrough(‘Wrapper’, props, this)}
    >
    styles={styles.Count}
    {…passthrough(‘Count’, props, this)}
    >
    {children}


    )
    );
    |> extract the node components removing the imports

    View Slide

  47. const getCounter = ({ Wrapper, Count, passthrough }) => (
    ({ children, styles }) => (
    styles={styles.Wrapper}
    {…passthrough(‘Wrapper’, props, this)}
    >
    styles={styles.Count}
    {…passthrough(‘Count’, props, this)}
    >
    {children}


    )
    );
    |> extract the node components removing the imports

    View Slide

  48. function passthrough(nodeName, props, instance) {
    switch(nodeName) {
    case ‘Wrapper’:
    return { counter: props.counter };
    default:
    return {};
    }
    }
    |> specify how do you want to pass down properties

    View Slide

  49. const Counter = getCounter({
    passthrough,
    Wrapper: styled.div`
    background-color: ${props => (
    props.counter > 10 && ‘red’
    )};
    height: 100px;
    width: 100px;
    `,
    Count: styled.span`
    color: white;
    display: block;
    text-align: center;
    `,
    })
    |> use the property to modify the style from its generation

    View Slide

  50. const Counter = getCounter({
    passthrough,
    Wrapper: styled.div`
    background-color: ${props => (
    props.counter > 10 && ‘red’
    )};
    height: 100px;
    width: 100px;
    `,
    Count: styled.span`
    color: white;
    display: block;
    text-align: center;
    `,
    })
    |> use the property to modify the style from its generation

    View Slide

  51. View Slide

  52. back to react-toolbox!
    the road for a final version.

    View Slide

  53. |> a brand new package!

    react-toolbox-core
    build your custom react ui-kit from a reliable set of
    agnostic components, hoc and utilities

    View Slide

  54. |> what’s coming with react-toolbox-core?
    an hoc to make navigable components
    complex components like a date picker
    an hoc to position elements in the screen

    View Slide

  55. |> react-toolbox v3!

    react-toolbox v3
    delightful material design components that will
    boost your project

    View Slide

  56. |> what’s coming with react-toolbox-core?
    customize render by injecting nodes
    customize styles without worrying about selectors
    js theming api powered by styled components
    powerful children based api

    View Slide

  57. thank you!

    View Slide