react-state-hoc
Version:
A React higher-order component for abstracting state away
122 lines (89 loc) • 3.81 kB
Markdown
[](https://badge.fury.io/js/react-state-hoc)
[](https://travis-ci.org/troch/react-state-hoc)
# React state component (higher-order)
> A React higher-order component for abstracting away state
Keep your components simple, testable, and composable by using higher-order components. This higher-order component will abstract state away from components, so you can keep using functional stateless components.
## Installation
```sh
npm install --save react-state-hoc
# or
yarn add react-state-hoc
```
## API
### withState(initialState, mapSetStateToProps?, mergeProps?)(BaseComponent)
Wraps your `BaseComponent` with a stateful component, passing the state into the `BaseComponent` as props. By default, state will be spread into the component's props, plus the `setState` function is passed through. If you specify a `mapSetStateToProps` function, `setState` will not be passed through.
Two optional arguments allow you to a) define state creators, and b) customise which props are passed into the `BaseComponent`.
* `initialState` can be either:
* An object, to be used as the component's initial state.
```js
withState({ visible: true })(BaseComponent)
```
* A function, which maps initial props to initial state.
```js
withState(props => ({ visible: props.visible }))(BaseComponent)
```
* `mapSetStateToProps` can be either:
* An object, containing state creators. Each state creator is a function which maps input arguments to new state. State creators are a convenient shorthand which automatically binds `setState` into smaller functions. Functions can also be provided as well as objects: they are supported by `setState` (see [https://reactjs.org/docs/react-component.html#setstate](https://reactjs.org/docs/react-component.html#setstate))
```js
withState(
{ visible: true },
{ setVisibility: visible => ({ visible }) }
)(BaseComponent)
```
* A function, mapping `initialProps` and `setState` to state creators.
```js
withState({ state: null }, initialProps => setState => ({
setValue: value => setState({
someState: initialProps.mapValue(value)
})
}))(BaseComponent)
```
**Default:**
```js
() => setState => ({ setState })
```
* `mergeProps`: A function mapping the current `props`, `state` and `stateCreators` into the `BaseComponent`'s props.
```js
withState(
{ visible: true },
{ setVisibility: visible => ({ visible }) },
(state, stateCreators, props) => ({
...state,
...stateCreators
// deliberately not passing props through to BaseComponent
})
)(BaseComponent)
```
**Default:**
```js
(props, state, stateCreators) => ({ ...props, ...state, ...stateCreators })
```
## Example
```javascript
import React from 'react'
import ReactDOM from 'react-dom'
import withState from 'react-state-hoc'
function StatelessButton({ counter, setCounter }) {
return (
<button onClick={() => setCounter(counter + 1)}>
Clicked {counter} times.
</button>
)
}
const mapSetStateToProps = () => setState => ({
setCounter: counter => setState({ counter })
})
const StatefulButton1 = withState({ counter: 0 }, mapSetStateToProps)(
StatelessButton
)
const StatefulButton2 = withState({ counter: 10 }, mapSetStateToProps)(
StatelessButton
)
ReactDOM.render(
<div>
<StatefulButton1 />
<StatefulButton2 />
</div>,
document.getElementById('app')
)
```