A higher-order component abstracting state away
MIT License
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.
npm install --save react-state-hoc
# or
yarn add react-state-hoc
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.
withState({ visible: true })(BaseComponent)
A function, which maps initial props to initial state.
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)
withState(
{ visible: true },
{ setVisibility: visible => ({ visible }) }
)(BaseComponent)
A function, mapping initialProps
and setState
to state creators.
withState({ state: null }, initialProps => setState => ({
setValue: value => setState({
someState: initialProps.mapValue(value)
})
}))(BaseComponent)
Default:
() => setState => ({ setState })
mergeProps
: A function mapping the current props
, state
and stateCreators
into the BaseComponent
's props.
withState(
{ visible: true },
{ setVisibility: visible => ({ visible }) },
(props, state, stateCreators) => ({
...state,
...stateCreators
// deliberately not passing props through to BaseComponent
})
)(BaseComponent)
Default:
(props, state, stateCreators) => ({ ...props, ...state, ...stateCreators })
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')
)