Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/colevoss/react-motive

Another React state management library using the new Context API
https://github.com/colevoss/react-motive

react react-context state-management

Last synced: about 2 months ago
JSON representation

Another React state management library using the new Context API

Awesome Lists containing this project

README

        

# React Motive [![npm](https://img.shields.io/npm/v/react-motive.svg)](https://www.npmjs.com/package/react-motive) [![npm](https://img.shields.io/npm/dm/react-motive.svg)](https://www.npmjs.com/package/react-motive) ![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/react-motive.svg) ![Travis](https://img.shields.io/travis/colevoss/react-motive.svg)

Small wrapper around the React Context API with actions/dispatch style state management.

## Install

```
yarn add react-motive
```

## Example

[![Edit React Motive Counter Example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/ll693wn0pl?module=%2Fsrc%2FCounter.js)

```js
import React from 'react';
import createMotive from 'react-motive';

/**
* Default State
*/
const defaultState = { count: 0 };

/**
* Actions:
*
* Actions don't have to be curried functions if they don't take arguments
* as long as dispatch is given a function that returns a new slice of state.
*/
const increment = () => ({ count }) => ({
count: count + 1,
});

const decrement = () => ({ count }) => ({
count: count - 1,
});

/**
* Create Container
*/
const Counter = createMotive(defaultState);

/**
* Use Consumers
*/
const Display = () => (

{({ state }) =>

Count: {state.count}

}

);

const Controls = () => (

{({ dispatch }) => (

dispatch(decrement())}>-
dispatch(increment())}>+

)}

);

/**
* Put it all together
*/
const AllTogether = () => (




);
```

## Documentation

#### `createMotive`

`createMotive` returns an object with a `Provider` component and a `Consumer` component.

```js
const defaultState = { count: 1 };

const { Provider, Consumer } = createMotive(defaultState);
```

#### ``

The `Provider` is a React component that should wrap all of its corresponding `Consumer` components. This component holds all of the state given from `defaultState` and that is updated later on.

#### ``

The `Consumer` component is what you can use anywhere as long as it's a child of the corresponding `Provider` component. Use this component to get access to the state of its `Provider` and to dispatch updates to that state.

```js

{({ state, dispatch }) => /* ... some react stuff that uses state or dispatch */ }

```

This component takes a render prop as its child. This render prop is given an object with the following members in it.

##### `state`

This is the current state of the corresponding `Provider` component.

#### `dispatch`

`dispatch` should be called with an `action` function. An `action` should return a slice of new state to be merged into the `Provider`'s state.

### Actions

Actions are provided with `state` and `dispatch` as arguments. This means you can dispatch other actions from an action if necessary.

An action must return a partial version of state.

**Pro Tip:** If you need to give actions data, write them as curried functions and call them into `dispatch` with any arugments that they might need.

```js
/**
* Basic action
*/
const increment = (state) => ({
count: state.count + 1,
});

dispatch(increment);

/**
* Curried action that takes arguments
*/
const incrementBy = (incrBy) => (state) => ({
count: state.count + incrBy,
});

dispatch(incrementBy(2));

/**
* Action that dispatches another action
*/
const delayedIncrement = (state, dispatch) => {
setTimeout(() => dispatch(incrementBy(2)));

return {
count: state.count + 1,
};
};

dispatch(delayedIncrement);
```

#### `combineActions`

`combineActions` will take two actions and combine their returned updated pieces of state into one updated piece of state.

```js
const defaultState = {
a: 0,
b: 0,
};

const actionA = (state) => {
return {
a: state.a + 1,
};
};

const actionB = (state) => ({
b: state.b + 2,
});

const combined = combineActions(actionsA, actionB);

const resultingState = dispatch(combined);

resultingState === { a: 1, b: 2 };
```