zoltantothcom / hocs

:gift: A collection of Higher-Order Components for React

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

@hocs ci coverage

A collection of Higher-Order Components for React, especially useful with Recompose.

A Higher-Order Component is a function that takes a component and returns a new component.

TOC

Packages

🚱 omitProps npm deps

yarn add recompose @hocs/omit-props
omitProps(
  ...props: Array<string>
): HigherOrderComponent
import React from 'react';
import { compose, withProps } from 'recompose';
import omitProps from '@hocs/omit-props';

const Demo = (props) => (
  <h1>props: {JSON.stringify(props)}</h1>
);

export default compose(
  withProps({ a: 1, b: 2, c: 3 }),
  omitProps('a', 'b')
)(Demo);
yarn start demo omit-props

Inspired by Reassemble, in comparison with Recompose lifecycle this HOC provides a handy (and limited) way to use some of React Component Lifecycle methods such as:

  • onWillMount(props)
  • onDidMount(props)
  • onWillReceiveProps(props, nextProps)
  • onWillUpdate(props, nextProps)
  • onDidUpdate(prevProps, props)
  • onWillUnmount(props)

So no this, setState or even constructor, you have no direct access to class instance anymore (:tada:).

yarn add recompose @hocs/with-lifecycle
withLifecycle(
  methods: Object
): HigherOrderComponent
import React from 'react';
import { compose, withState } from 'recompose';
import withLifecycle from 'with-lifecycle';

const Demo = ({ isLoading }) => (
  <h1>{ isLoading ? 'Loading' : 'Done' }</h1>
);

export default compose(
  withState('isLoading', 'setLoading', false),
  withLifecycle({
    onDidMount({ setLoading }) {
      setLoading(true, () => {
        setTimeout(() => setLoading(false), 3000);
      })
    },
    onWillUnmount() {
      console.log('bye');
    }
  })
)(Demo);

In addition, it can handle a factory function which works like Recompose withHandlers factory:

withLifecycle(
  methodsFactory: (initialProps: Object) => methods: Object
): HigherOrderComponent
withLifecycle(
  ({ shouldLoadOnMount }) => {
    if (shouldLoadOnMount) {
      return {
        onDidMount({ setLoading }) {
          setLoading(true, () => {
            setTimeout(() => setLoading(false), 1000);
          })
        }
      };
    }
  }
)
yarn start demo with-lifecycle

As a bonus you can "share" stuff across different lifecycle methods in that factory scope with let mySharedStuff, just like you did before with this.mySharedStuff using a class instance.

yarn add recompose @hocs/debounce-handler
debounceHandler(
  handlerName: string,
  delay: ?number,
  leadingCall: ?boolean
): HigherOrderComponent
import React from 'react';
import { compose, withState, withHandlers } fgrom 'recompose';
import debounceHandler from '@hocs/debounce-handler';

const Demo = ({ count, onButtonClick }) => (
  <div>
    <h1>{count}</h1>
    <button onClick={onButtonClick}>CLICK ME FAST</button>
  </div>
);

export default compose(
  withState('count', 'setCount', 0),
  withHandlers({
    onButtonClick: ({ count, setCount }) => () => setCount(count + 1)
  }),
  debounceHandler('onButtonClick', 300)
)(Demo);
yarn start demo debounce-handler
yarn add recompose @hocs/throttle-handler
throttleHandler(
  handlerName: string,
  interval: ?number,
  leadingCall: ?boolean
): HigherOrderComponent
import React from 'react';
import { compose, withState, withHandlers } fgrom 'recompose';
import throttleHandler from '@hocs/throttle-handler';

const Demo = ({ count, onButtonClick }) => (
  <div>
    <h1>{count}</h1>
    <button onClick={onButtonClick}>CLICK ME FAST</button>
  </div>
);

export default compose(
  withState('count', 'setCount', 0),
  withHandlers({
    onButtonClick: ({ count, setCount }) => () => setCount(count + 1)
  }),
  throttleHandler('onButtonClick', 300)
)(Demo);
yarn start demo throttle-handler

Development

  1. See how existing HOCs are done, especially their package.json files.
  2. Create a new folder in packages/, let's say with-foo.
  3. Put source code in with-foo/src/, it will be transpiled and bundled into with-foo/dist/, with-foo/lib/ and with-foo/es/.
  4. Put tests written with Jest in with-foo/test/.
  5. Put demo in with-foo/demo/, it will be rendered and wrapped with HMR.
  6. See Start.
  7. Done.
yarn
yarn start build <package>
yarn start demo <package>
yarn start test
yarn start testWatch
yarn start lint

About

:gift: A collection of Higher-Order Components for React

License:MIT License


Languages

Language:JavaScript 100.0%