ALTERNATE PATTERNS FOR REUSABILITY​ IN REACT

ESPEN HENRIKSEN

@espen_dev

@esphen​

​Components

Components are the primary unit of code reuse in React

Advantages

  • The first thing you learn in React​
  • ​Pretty easy to understand

​Case:

​You want to fetch something from a server and show a loading spinner

Loading component

// SomeComponent.js

import React from 'react';
import Loading from './LoadingComponent';

export default props => {
  if (props.loading) <Loading />;
  return <div>{props.data}</div>;
};
// LoadingComponent.js

import React from 'react';

export default () => <i className="fa fa-spinner fa-spin" />;

Issues with "LoadingComponent"​

  • Imperative rendering
  • ​Cognitive overhead in render
  • Bad solution for cross-cutting concerns

​Higher order components

​Use HOCs For Cross-Cutting Concerns

a higher-order component is a function that takes a component and returns a new component

const EnhancedComponent = higherOrderComponent(WrappedComponent);

Why?

Advantages​

  • Encourages functional components
  • Composition
  • Makes components testable

​Case:

​You want to fetch something from a server and show a loading spinner

import React from 'react';
import { compose } from 'recompose';
import fetch from 'fetch-hoc';
import { withLoading, withError } from './loading';

export const FooComponent props => (
  <div>{props.data}</div>
);

export default compose(
  fetch('/some/data'),
  withLoading,
  withError('Failed to fetch that stuff'),
)(FooComponent);

​Component can focus on rendering the data

export const FooComponent props => <div>{props.data}</div>;
// react-apollo
export const GraphQLComponent = graphql(gql`
  query MyQuery {
    todos { text } 
  }
`)(FooComponent);
// react-router
export const ReactRouterComponent = withRouter(FooComponent);
// recompose
export const StatefulFunctionalComponent = compose(
  withState('count', 'setCount', 0),
  withHandlers({
    incrementCount: props => () => {
      props.setCount(props.count + 1);
    },
  }),
 )(FooComponent);
// redux & fetch-hoc
export const ComponentWithData = fetch(
  connect(state => ({ userId: state.user.id })),
  fetch(props => `/user/${props.userId}/cart`),
)(FooComponent);

​fetch-hoc

github.com/esphen/fetch-hoc

​Tagged template literals

​an API that makes many tasks related to creating and parsing strings simple

Tagged template literals

var person = 'Mike';
var age = 28;

function myTag(strings, personExp, ageExp) {

  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  return str0 + personExp + str1 + ageStr;

}

var output = myTag`that ${person} is a ${age}`;

console.log(output);
// that Mike is a youngster

Why?​

  • String formatting
  • Can output anything
  • Makes new patterns possible
import React from 'react';
import f from 'format';

export const Texts = props => (
  f`Hello ${props.name}, you have ${props.amount}:cur(NOK) in your bank account.`
);

export const UserInfo = props => (
  <ul>
    <li>{f`Username: ${props.username}:uid`}</li>
    <li>{f`You have ${props.pets}:num unread messages`}</li>
  </ul>
);

​A hypothetical formatting library

styled-components​

A library for css-in-js

styled-components

const Button = styled.a`
	display: inline-block;
	border-radius: 3px;
	padding: 0.5rem 0;
	margin: 0.5rem 1rem;
	width: 11rem;
	color: white;

	/* "Change styling" based on props */
	${props => props.primary && css`
		background: white;
		color: palevioletred;
	`}
`

export default () => [
    <Button />
    <Button primary />
];

i18n​

​Compiler/bundler plugins

  • Bullet One
  • Bullet Two
  • Bullet Three

​Advantages

  • No runtime overhead
  • Global reach
  • AOT optimizations
    • Performance

webpack-i18n-plugin

import React from 'react';

const selectFruit = () => {
  alert(__('You selected a fruit. Good on you!'));
};

export default props => (
  <form onSubmit={selectFruit}>
    {__('Choose fruit')}
    <input type="text" placeholder={__('Fruit')} />
  </form>
);

​Portals

  • Bullet One
  • Bullet Two
  • Bullet Three

Codemods

  • Bullet One
  • Bullet Two
  • Bullet Three

Don't be afraid to think outside the box​

Questions?

slides.com/esphen/​alternate-patterns-for-reusability​

Made with Slides.com