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

React component patterns

React component patterns

Dawid Jankowiak

October 17, 2017
Tweet

More Decks by Dawid Jankowiak

Other Decks in Programming

Transcript

  1. const ApplicantInfoPage = ({ data, isLoading, error }) => {...};

    export default withFetch( ownProps => `/api/applicants/${ownProps.match.props.id}` )(ApplicantInfoPage);
  2. const withFetch = urlGetter => BaseComponent => class WithFetch extends

    React.Component { state = { isLoading: true, error: null, data: null }; static displayName = `WithFetch(${wrapDisplayName( BaseComponent )})`;
  3. componentDidMount() { axios .get(urlGetter(this.props)) .then(({ data }) => this.setState({ data,

    isLoading: false })) .catch(error => this.setState({ error, isLoading: false })); }
  4. render() { if (this.state.isLoading === true) { return <Loading />;

    } if (this.state.error !== null) { return <ErrorPanel />; } return <BaseComponent {...this.props} data={this.state.data} />; } };
  5. Lets you mix behaviours Simple to use Composable (like regular

    function composition) Applicable before use (cannot be used in render function) Refs aren’t passed through Static methods must be copied over
  6. Downshift React-Motion React-Router v4 react-virtualized Passing a function to a

    component (as a prop or children of component) that tells it what to render
  7. <Paging items={itemsArray} itemsPerPage={10} render={item => ( <div>{item.name}</div> )} />; <Paging

    items={itemsArray} itemsPerPage={10} > {item => ( <div>{item.name}</div> )} </Paging>;
  8. class Paging extends Component { … render() { const items

    = this.getItems(); return ( <div> {items.map(this.prop.render)} {this.renderButtons()} </div> ); } } class Paging extends Component { … render() { const items = this.getItems(); return ( <div> {items.map(this.prop.children)} {this.renderButtons()} </div> ); } }
  9. Used as regular components Simple to implement Dynamic in nature

    Nesting (hell?) Returning large component tree may introduce performance problems
  10. const Item = ({ children, isHighlighted }) => ( <section

    className={isHighlighted ? 'highlighted' : ''}> {children} </section> )
  11. class Carousel extends Component { state = { activeIndex: null

    }; render() { const { state: { activeIndex }, props: { children } } = this; return ( <div> <PrevButton onClick={this.handlePreviewClick()} /> {this.getActiveItem(children, activeIndex)} {this.getDottedMenu(children)} <NextButton onClick={this.handleNextClick()} /> </div> ); }
  12. ... getActiveItem(items, activeIndex) { const item = React.Children.toArray(items).find((item, index) =>

    { if (activeIndex !== null) return index === activeIndex; return item.props.active === true; }); return React.cloneElement(item, { isHighlighted: true }); } ...
  13. Enables creating general purpose sharable components Require a lot of

    imperative manual work Local state harder to manage from outside
  14. Component with State Machine, inspired by ReasonReact, feels like Redux

    in component Rediscovered from recompose (bet all familiar with redux had this idea)
  15. class Counter extends ReducerComponent { state = { count: 0

    }; increment(_e) { return "increment"; } decrement(_e) { return "decrement"; }
  16. reducer(state, action) { switch (action) { case "increment": return {

    count: state.count + 1 }; case "decrement": return { count: state.count - 1 }; } }
  17. class ReducerComponent extends React.Component { reducer(state, action) { return state;

    } dispatch(actionCreator) { return (...eventArgs) => { this.setState((prevState, _props) => { this.reducer(prevState, actionCreator(...eventArgs)); }); }; } }
  18. Simple to manage a complex state For small apps/complex local

    states Requires familiarity with a reducing state Not needed when other State libraries are present (Redux/MobX)
  19. Higher Order Component Lets you add behaviour to components Function

    As a Child (Render Function) Lets you focus on what will be rendered Compound Components Lets you create groups of components with shared state Reducer Component Lets you manage a component state in a single place