reclass

0.2.1 • Public • Published

reclass

Build Status npm version Coverage Status

TL;DR

  • Write React stateful components without worrying about this or binding methods.
  • No more this.myMethod = this.myMethod.bind(this);. Whatz!?
  • Write your methods using ES6 "fat arrow" functions.
  • A no-frill/smaller footprint alternative to recompose.

Install

$ npm i --save reclass

Usage

import React from 'react';
import reclass from 'reclass';

const MyComponent = (ctx) => {
  const { setState } = ctx;

  const clickHandler = () => {
    setState({...});
  };

  const render = (props, state, context) => (
    ...
    <RenderSomething onClick={clickHandler} />
  );

  return {
    state: {...},
    render,
  };
};

export default reclass(MyComponent);

Let's break it down...

First of all, you write your stateful component as a simple JavaScript function and NOT an ES6 class. This function is responsible for doing a few things:

  • Accepts a ctx context object as an argument (see explaination of ctx below).

    const MyComponent = (ctx) => {
  • Returns a properties object which defines your component. At a minimun, you'll probably want to return a render function and a state object that represents your component's initial state.

    return { // Return initial state and public methods
      state: {...}, // Initial state
      render,
    };
  • Exposes optional static propTypes and defaultProps properties.

    MyComponent.propTypes = {
      ...
    };
    
    MyComponent.defaultProps = {
      ...
    };

Before you export your component, you wrap it using reclass.

export default reclass(MyComponent);

The ctx argument

You will be passed a ctx object with the following properties and methods:

  • setState - This is the same setState that you are used to, but you can forget the this.

    💡 Pro Tip: Destructure setState for ease of use.

    Example:

    const MyComponent = (ctx) => {
      const { setState } = ctx;
      ...
      setState({ partial });
  • state - A getter/setter for state. As a getter, this is same as this.state. Note that both props are state and passed to render, so, depending on your applications you may not need to access these from ctx directly.

    💡 Pro Tip: With reclass, you can set state directly without consequence. You can use this instead of calling setState.

    Example:

    const MyComponent = (ctx) => {
      ...
      ctx.state = { partial }; // same as setState({ partial });
  • props - A getter for props.

  • context - A getter for context.

render

In all likelihood, you will have a render method. render works exactly as you might expect, except that you are passed props, state, and context.

💡 Pro Tip: You can destructure props, state, and context inline as parameters.

Example:

const render = ({ someProp }, { someStateValue }) => (
  ...
);

You will also notice that your render method (all methods for that fact) can be written in ES6 "fat arrow" style.

Example

Below is an example of a 'Greeter' component written using reclass. You can see it running live on CodeSandbox.

import React from 'react';
import PropTypes from 'prop-types';
import reclass from 'reclass';
import GreeterView from './GreeterView';

const Greeter = (ctx) => {
  const changeName = (name) => {
    ctx.state = { name };
  };

  const render = ({ greeting }, { name }) => (
    <GreeterView
      greeting={greeting}
      name={name}
      onNameChange={changeName}
    />
  );

  return {
    state: { name: 'John' }, // Initial state
    render,
  };
};

Greeter.propTypes = {
  greeting: PropTypes.string,
};

Greeter.defaultProps = {
  greeting: '',
};

export default reclass(Greeter);

Really?

OK. Adding all of that code in a closure doesn't come without a price. It can use more memory than class-based components where methods are on the prototype and not on each class instance. There are a few things that make this moot.

If you have a component that has hundreds or even thousands of instances, this will be a factor. But if you have only a few instances, or even a single instance, this isn't a concern.

In any case, I suggest that you follow the Single Responsibility Principle and break out the rendering responsibility from the state management responsibility. Rendering, therefore, can he handled in a stateless functional component. See an example of this here.

Package Sidebar

Install

npm i reclass

Weekly Downloads

0

Version

0.2.1

License

MIT

Last publish

Collaborators

  • donavon