0.1.0 • Published 6 years ago

rp-hoc v0.1.0

Weekly downloads
2
License
MIT
Repository
github
Last release
6 years ago

rp-hoc

Convert between Render Props and HOC

PackageVersionDependenciesDevDependenciesBuild
rp-hocnpm (scoped)Dependency StatusdevDependency StatusBuild Status

Install

Install from npm:

npm install rp-hoc --save

Import:

import { toRP, withRP } from 'rp-hoc';

If you use decorator with Babel please run this command:

npm install --save-dev babel-plugin-transform-decorators-legacy

And modify the .babelrc file to enable the plugin:

{
  "plugins": ["transform-decorators-legacy"]
}

APIs

toRP(decorator, options)

Convert the decorator to a render-props component.

Options:

OptionDefault valueUsageTests
renderKey'children'change the callback key in props.test/hoc-to-rp/react-redux.js#L92-L117
useComponentfalseUse React.Component to create new component instead of Stateless Component.test/hoc-to-rp/react-redux.js#L119-L149
usePureComponentfalseUse React.PureComponent to create new component instead of Stateless Component.test/hoc-to-rp/react-redux.js#L151-L181

Example React Redux

Use decorator:

@connect(
  mapStateToProps,
  mapDispatchToProps,
)
class App extends Component {
  render() {
    const { counter, inc, dec } = this.props;
    return (
      <div>
        <div id="counter">{counter}</div>
        <button id="inc" onClick={() => inc()}>Increment</button>
        <button id="dec" onClick={() => dec()}>Decrement</button>
      </div>
    );
  }
}

Use render-props component:

const Connect = toRP(
  connect(
    mapStateToProps,
    mapDispatchToProps,
  ),
);

const App = () => (
  <Connect>
    {({ counter, inc, dec }) => (
      <div>
        <div id="counter">{counter}</div>
        <button id="inc" onClick={() => inc()}>Increment</button>
        <button id="dec" onClick={() => dec()}>Decrement</button>
      </div>
    )}
  </Connect>
);

Use different renderKey:

const Connect = toRP(
  connect(
    mapStateToProps,
    mapDispatchToProps,
  ), {
    renderKey: 'myRender', // this line changed
  },
);

const App = () => (
  <Connect
    // this line changed
    myRender={({ counter, inc, dec }) => (
      <div>
        <div id="counter">{counter}</div>
        <button id="inc" onClick={() => inc()}>Increment</button>
        <button id="dec" onClick={() => dec()}>Decrement</button>
      </div>
    )}
  />
);

withRP(element, options) and withRP(component, props, options)

Convert the render-props component to a decorator.

Options:

OptionDefault valueUsageTests
renderKey'children'change the callback key in props.test/rp-to-hoc/react-value.js#L31-L49
multiArgsnullConvert callback arguments to Array. Otherwise callback props will be assigned with original props by Object.assign.test/rp-to-hoc/react-value.js#L31-L49

Example React Value

Use render-props component:

import Toggle from 'react-toggled';
const App = () => (
  <Toggle defaultOn>
    {({ on, getTogglerProps }) => (
      <div>
        <button {...getTogglerProps()}>Toggle me</button>
        <div id="result">{on ? 'Toggled On' : 'Toggled Off'}</div>
      </div>
    )}
  </Toggle>
);

Use heigher-order component:

const WithToggle = withRP(<Toggle defaultOn />);

@WithToggle
class App extends Component {
  render() {
    const { on, getTogglerProps } = this.props;
    return (
      <div>
        <button {...getTogglerProps()}>Toggle me</button>
        <div id="result">{on ? 'Toggled On' : 'Toggled Off'}</div>
      </div>
    );
  }
}

To prevent prop-types warning, you can use withRP(component, props, options):

const WithToggle = withRP(Toggle, { defaultOn: true });

@WithToggle
class App extends Component {
  render() {
    const { on, getTogglerProps } = this.props;
    return (
      <div>
        <button {...getTogglerProps()}>Toggle me</button>
        <div id="result">{on ? 'Toggled On' : 'Toggled Off'}</div>
      </div>
    );
  }
}