0.0.4 • Published 6 years ago

react-app-state v0.0.4

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

AppState

A simple state manager for React.

Installation

npm install --save react-app-state

AppState is intended to be 100% compatible with create-react-app.

Usage

Instantiate an AppState manager and initialize the variables it will keep:

// --- fooState.js ---
import AppState from 'react-app-state';

let fooState = new AppState({ myName: '' });
export default fooState;

If a component wants to update the state, it calls set method passing the variables to be updated:

// --- InputComponent.js ---
import React from 'react';
import fooState from './fooState';

const InputComponent = () => (
  <div>
    Name:
    <input type="text"
      onChange={ev =>
        fooState.set({ myName: ev.target.value })
      }/>
  </div>
);

export default InputComponent;

If a component wants to consume the state, it calls subscribe, which returns a HOC. The subscribed variables then come through props:

// --- DisplayComponent.js ---
import React from 'react';
import fooState from './fooState';

const DisplayComponent = ({ myName }) => (
  <div>
    My name is {myName}.
  </div>
);

export default fooState.subscribe(DisplayComponent);

Extending AppState

Extending AppState is useful to enforce business logic, or just to add a layer over the raw stored values.

// --- nameOwner.js ---
import AppState from 'react-app-state';

class NameOwner extends AppState {
  constructor() {
    super({ myName: 'Mr. Doe' });
  }

  chooseMyName(name) {
    super.set({ myName: 'Mr. ' + name });
  }
}

export default new NameOwner();

Updating the state:

// --- InputComponent.js ---
import React from 'react';
import nameOwner from './nameOwner';

const InputComponent = () => (
  <div>
    Name:
    <input type="text"
      onChange={ev =>
        nameOwner.chooseMyName(ev.target.value)
      }>
  </div>
);

export default InputComponent;

And consuming:

// --- DisplayComponent.js ---
import React from 'react';
import nameOwner from './nameOwner';

const DisplayComponent = ({ myName }) => (
  <div>
    My name is {myName}.
  </div>
);

export default nameOwner.subscribe(DisplayComponent);

Computed values

Extending AppState is also useful to provide computed values. Taking the previous example, we could choose to store myName as typed by the user and have a method to return the computed string:

// --- nameOwner.js ----
import AppState from 'react-app-state';

class NameOwner extends AppState {
  constructor() {
    super({ myName: '' });
  }

  get prettyName() { // a getter, could be an ordinary function too
    return 'Mr. ' + super.get('myName');
  }

  chooseMyName(name) { // could also be a setter
    super.set({ myName: name });
  }
}

export default new NameOwner();

Consuming the computed value:

// --- DisplayComponent.js ---
import React from 'react';
import nameOwner from './nameOwner';

const DisplayComponent = () => (
  <div>
    My name is {nameOwner.prettyName}.
  </div>
);

export default nameOwner.subscribe(DisplayComponent);

Multiple subscriptions

A component can subscribe to any number of AppState managers. Since subscribe returns a component, just chain the calls:

nameOwner.subscribe(
  anotherState.subscribe(
    yetAnotherManager.subscribe(DisplayComponent)
  )
);

The component will receive the variables of all those managers via props. Just beware name collisions: if two variables have the same name, the last one will prevail.

@subscribe decorator

If you're using decorators on your project, you can alternatively subscribe to an AppState manager instance like this:

// --- DisplayComponent.js ---
import React, {Component} from 'react';
import {subscribe} from 'react-app-state';
import nameOwner from './nameOwner';

@subscribe(nameOwner)
class DisplayComponent extends Component {
  render() {
    return (
      <div>
        My name is {this.props.myName}.
      </div>
    );
  }
}

export default DisplayComponent;

This decorator is pure syntactic sugar: internally, @subscribe simply calls the subscribe method of the AppState manager, so it's the same thing.

And multiple subscriptions can be done as well:

@subscribe(nameOwner, anotherState, yetAnotherManager)
class DisplayComponent {

Full API documentation

AppState(propsAndValues) – constructor. Instantiates AppState and initializes the values to be kept.

AppState.subscribe(WrappedComponent) – subscribes a component to the state manager instance. The component will receive the variables through its props. A component can subscribe to any number of AppState instances.

AppState.get(propName) – retrieves a value imperatively.

AppState.set(propsAndValues, callback) – updates the internal state, propagating the new values to the subscribed components. The 1st argument contains the values to be updated. The 2nd argument is a callback to be called after the state is set, just like an ordinary setState call works.

@subscribe(managers) – subscribe a class to one or more AppState managers.

0.0.4

6 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago