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

React Alicante 17' - Writing highly reusable Re...

Javier Velasco
October 06, 2017
220

React Alicante 17' - Writing highly reusable React components

Javier Velasco

October 06, 2017
Tweet

Transcript

  1. A library of React components implementing Material Design guidelines with

    the power of CSS modules. www.react-toolbox.com React Toolbox
  2. 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
  3. “let’s change the color scheme so all components have a

    different primary color” |> you predict what’s going to be changed theming
  4. “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
  5. “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
  6. theming + style customization + render customization |> taking customization

    to the limits, adapt to nearly anything fully flexible component + +
  7. 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
  8. |>css in js enforcing hate and the js fatigue since

    2015 ® my favorite: styled components |> css-in-js: let’s the building
  9. 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
  10. 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
  11. 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
  12. 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
  13. |> 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.
  14. const Button = ({ children, primary, ...other }) => (

    <button className={primary ? 'btn primary’ : 'btn'} {…other} > {children} </button> ); |> using react elements as primitives
  15. const Button = ({ children, primary, ...other }) => (

    <button className={primary ? 'btn primary’ : 'btn'} {…other} > {children} </button> ); |> using react elements as primitives
  16. |> 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.
  17. 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
  18. 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
  19. const theme = { main: 'mediumseagreen' }; render( <ThemeProvider theme={theme}>

    <Button>Themed </Button> </ThemeProvider> ) |>theming with styled-components
  20. const theme = { main: 'mediumseagreen' }; render( <ThemeProvider theme={theme}>

    <Button>Themed </Button> </ThemeProvider> ) |>theming with styled-components
  21. const Button = styled.button` border-radius: 3px; font-size: 1em; margin: 1em;

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

    padding: 0.25em 1em; ${props => props.styles}; `; |> style customization with styled-components
  23. const styles = css` color: black; border-radius: 50%; background-color: ${props

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

    => ( props.primary ? ‘aliceblue’ : undefined )}; ` |>style customization with styled-components
  25. const Counter = ({ children, styles }) => ( <Wrapper

    styles={styles.Wrapper}> <Count styles={styles.Count}> {children} </Count> </Wrapper> ); |>style customization with styled-components
  26. const myCounter = { Wrapper: css` background: gray; border: 1px

    solid darkgray; `, Count: css` color: red; text-decoration: underline; ` }; |>style customization with styled-components
  27. import Wrapper from ‘./Wrapper’; import Counter from ‘./Counter’; const Counter

    = ({ children, styles }) => ( <Wrapper styles={styles.Wrapper}> <Count styles={styles.Count}> {children} </Count> </Wrapper> ); |>back to the previous example
  28. const getCounter = ({ Wrapper, Count }) => ( ({

    children, styles }) => ( <Wrapper styles={styles.Wrapper}> <Count styles={styles.Count}> {children} </Count> </Wrapper> ) ); |>extract the node components removing the imports
  29. 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
  30. 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
  31. 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
  32. |> what if I want to have a red background

    when count value is higher than 10?
  33. const getCounter = ({ Wrapper, Count, passthrough }) => (

    ({ children, styles }) => ( <Wrapper styles={styles.Wrapper} {…passthrough(‘Wrapper’, props, this)} > <Count styles={styles.Count} {…passthrough(‘Count’, props, this)} > {children} </Count> </Wrapper> ) ); |> extract the node components removing the imports
  34. const getCounter = ({ Wrapper, Count, passthrough }) => (

    ({ children, styles }) => ( <Wrapper styles={styles.Wrapper} {…passthrough(‘Wrapper’, props, this)} > <Count styles={styles.Count} {…passthrough(‘Count’, props, this)} > {children} </Count> </Wrapper> ) ); |> extract the node components removing the imports
  35. function passthrough(nodeName, props, instance) { switch(nodeName) { case ‘Wrapper’: return

    { counter: props.counter }; default: return {}; } } |> specify how do you want to pass down properties
  36. 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
  37. 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
  38. |> a brand new package! react-toolbox-core build your custom react

    ui-kit from a reliable set of agnostic components, hoc and utilities
  39. |> 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
  40. |> 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