react-skinnable

Light decorator for react components to split logic and rendering

Usage no npm install needed!

<script type="module">
  import reactSkinnable from 'https://cdn.skypack.dev/react-skinnable';
</script>

README

react-skinnable

Light decorator to split logic and rendering helping readability and testing

Install

npm i --save react-skinnable

Usage

@skinnable decorator can only be applied to React.Component(s) classes. It requires you to add a function template and getLocals.

getLocals is where the logic stands: here you can apply transformations to props. getLocals must always return an object of locals.

getLocals(props) {
  const { firstName, lastName, age } = props;
  return {
    // example of simple transformations of `props`
    age: `${age} years old`,
    fullName: `${firstName} ${lastName}`
  };
}

template is the equivalent of a simple pure render that does no apply any transformation to the locals it receives in input. template must always return a renderable value (as render would).

template(locals) {
  const { fullName, age } = locals;
  return (
    <div>
      <h1>{fullName}</h1>
      <h3>{age}</h3>
    </div>
  );
}

@skinnable adds a method render to a component with getLocals and template so to make it compatible with React lifecycle.

@skinnable
export default class MyComponent extends React.Component {

  getLocals(props) {
    const { firstName, lastName, age } = props;
    return {
      // example of simple transformations of `props`
      age: `${age} years old`,
      fullName: `${firstName} ${lastName}`
    };
  }

  template(locals) {
    const { fullName, age } = locals;
    return (
      <div>
        <h1>{fullName}</h1>
        <h3>{age}</h3>
      </div>
    );
  }

}

// This is the actual returned component AFTER @skinnable does its job:

class MyComponent extends React.Component {

  getLocals(props) {
    const { firstName, lastName, age } = props;
    return {
      // example of simple transformations of `props`
      age: `${age} years old`,
      fullName: `${firstName} ${lastName}`
    };
  }

  template(locals) {
    const { fullName, age } = locals;
    return (
      <div>
        <h1>{fullName}</h1>
        <h3>{age}</h3>
      </div>
    );
  }

  render() {
    this.template(this.getLocals(this.props));
  }

}