simpply

3.2.1 • Public • Published

simpply

A simple state management library for React app, built on top of the Context & Hooks APIs.

Table of contents

Installation

Run npm i simpply.

Defining the notion of a Storage Entity

A Storage Entity in simpply is just an object which has two properties - initialState and effects. It defines a state for a particular system resource (or entity) and how it behaves or changes over time.

Below you have an example of a User Storage Entity that could be separated in a file called users.js:

// This goes in `users.js`.
 
/*
 * We are adding a new user (defined by the `payload` construct).
 *
 * E.g. for a first time add:
 * `state` would be the `initialState` (that is `[]`).
 * `payload` would be `John Doe`.
 */
const addUser = (state, payload) => [...state, payload];
 
const effects = {
  ADD_USER: addUser,
};
 
export default {
  initialState: [],
  effects,
};

An effect is a function that has the following signature: (state, payload). state represents the current value of the Storage Entity we apply the effect for. payload represents the data passed through the system when a certain action will be dispatched (more on that later).

Why are Storage Entities important

simpply provides an API so that all the Storage Entities in the system are combined into a System Storage. A System Storage is, in the context of simpply, just a fancy name that describes an object containing the system's state and all the effects associated with it (and that will change the state over time). The System Storage is used to create the final store (state + dispatch) by employing the userReducer hook in React.

Documentation

createSystemStorage

/**
 * @param {Object} storageEntitiesObj An object containing all the Storage Entities in the app.
 * @returns {Object} An object containing the global initial state of the system and all the effects associated with it.
 */

Combines all the Storage Entities in the app under the same umbrella. A Storage Entity file must contain the following two exports:

{
  // Can be any primitive type, except `undefined` and `Symbol`
  initialState: ...,
  // Collection of effects
  effects: ...;
}

For details on what each property represents, check the above documentation for Storage Entity.

E.g. of a User Storage Entity implementation with an effect to add a new user, a Puppy Storage Entity with an effect to delete a puppy and how they are combined via createSystemStorage:

// In `users.js`
 
export default {
  initialState: [],
  effects: {
    ADD_USER: (state, payload) => [...state, payload],
  },
};
 
// In `puppies.js`
 
export default {
  initialState: [],
  effects: {
    ADD_PUPPY: (state, payload) => [...state, payload],
  },
};
 
// Then in a separate file (e.g.: `systemStorage.js`), combine the two:
 
import users from '/path/to/users.js';
import puppies from '/path/to/puppies.js';
 
export default createSystemStorage({
  users,
  puppies,
});

This function returns an object containing the global initial state of the system and all the effects associated with it. The end result of applying createSystemStorage will then be used to create the application's main Provider.

createProvider

/**
 * @param {Object} systemStorage The combination of all the Storage Entities in the app.
 * @param {Object} options A object defining the configuration for `simpply`.
 * @return {React.FunctionComponentElement} Returns the app's `Provider` component.
 */

Creates the application's main Provider component that serves the resulting store via Context API.

E.g. of using createProvider:

// In index.js
 
import { createProvider } from 'simpply';
import systemStorage from '/path/to/systemStorage.js';
 
const AppProvider = createProvider(systemStorage, {
  logging: false,
});
 
ReactDOM.render(
  <AppProvider>...</AppProvider>,
  document.getElementById('root')
);

The options object looks like this:

{
  // [Boolean] Specifies if logging for the last triggered action, previous & current state is enabled. Defaults to `true` in `development` and `false` otherwise.
  logging: true,
  // [Boolean] Specifies if `getState` method is attached to `window` for debugging purposes. Defaults to `true` in `development` and `false` otherwise.
  globallyDebugState: true,
}

connect

/**
 * @param {Function | Null} mapStateToProps A function returning an object defining which slice of the global state will be injected in the wrapper component. If `mapStateToProps` is `null`, only `dispatch` will be injected.
 * @returns {Function} A HOF to apply to a React component.
 */

Creates a Higher Order Function (HOF) that can be later applied to a React component. The result of applying the function is a wrapper component that will have a slice of the global state automatically injected as well as the dispatch function.

E.g. of using connect for a PuppiesList component:

// In `PuppiesList.js`
 
import { connect } from 'simpply';
 
const PuppiesList = ({ puppies }) => (
  <ul>
    {puppies.map((puppy) => (
      <li key={puppy.id}>{puppy.name}</li>
    ))}
  </ul>
);
 
const mapStateToProps = (state) => ({
  /*
   * This is where we define that `PuppiesList` cares only about
   * the `puppies` property from the global state.
   */
  puppies: state.puppies,
});
 
export default connect(mapStateToProps)(PuppiesList);

The connect function is similar to Redux's connect functionality. However, it does not need a mapDispatchToProps function. dispatch is automatically injected in the connected component and simpply encourages making use of it directly. Below you have an example of dispatching, as a result of a successful async call.

// In MyComponent.js
 
const MyComponent = ({ dispatch }) => {
  useEffect(() => {
    (async () => {
      const res = await fetch('/path/to/url');
      const json = await res.json();
 
      // Just simply dispatch an action with the effect name and the payload
      dispatch({
        type: 'EFFECT_NAME',
        payload: json,
      });
    })();
  }, []);
 
  return <div>{/* Some markup here ... */}</div>;
};

Examples

For an example that uses simpply, check out this repo.

Author

Name: Vlad Zelinschi

Email: the.reignn@gmail.com

License

MIT © Vlad Zelinschi

Package Sidebar

Install

npm i simpply

Weekly Downloads

3

Version

3.2.1

License

MIT

Unpacked Size

19 kB

Total Files

5

Last publish

Collaborators

  • vladzelinschi