Skip to content

donavon/reclass

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

Write React stateful components without worrying about this or binding methods.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published