hooked-on-redux
v0.6.0
Published
A simple global state container for React apps
Downloads
92
Readme
Hooked on Redux is a React hook that lets you wield the power of Redux with an interface that's as simple as the useState
hook.
Redux is a great way to manage React state and its core principle: a single, immutable application state, allows for great features like hot reloading and time travel debugging. Unfortunately, Redux is also intimidating to learn for beginners and requires a lot of boilerplate that can slow down application development and add overhead to your codebase.
Hooked on Redux attempts to address these shortcomings by managing actions, selectors and reducers behind the scenes and exposing a simplified hook that lets you update Redux state in the same way you would update local component state with the useState
hook.
It looks like this:
const Example = props => {
const [count, setCount] = useHookedOnState('app.components.counterValue', 0)
return (
<main>
<p>You clicked {count} times.</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</main>
)
}
Getting Started
Installation
Hooked on Redux requires react-redux
as a peer dependency. You'll also need react
, react-dom
, and redux
if you don't have them installed already. This guide also assumes you are using npm and a module bundler like webpack. To get started:
npm i hooked-on-redux react-redux redux react-dom react
Importing Dependencies
Hooked on Redux works with Redux and React, so we need to install all of the typical dependencies as well as hooked-on-redux
.
Hooked on Redux can also work with your existing React/Redux app, so if you already have React and Redux installed you can skip importing from react
, react-dom
, redux
and react-redux
.
import React from 'react'
import ReactDOM from 'react-dom'
import {createStore} from 'redux'
import {Provider} from 'react-redux'
import {createHookedOnReducer, useHookedOnState} from 'hooked-on-redux'
The Store
Hooked on Redux uses a Redux store (either a new or existing one) along with a reducer creator called createHookedOnReducer
. This reducer creator will automatically manage state transformations so you won't need to think about reducers, actions or action creators.
const reducer = createHookedOnReducer()
const store = createStore(reducer, {})
Provider
Hooked on Redux leverages the <Provider />
component from react-redux
. If you've ever used Redux with React before you are probably already familiar with this step. In fact, most of this code should look identical to the react-redux quick start guide.
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('app')
)
The Hook
You are now ready to start writing components using useHookedOnState
.
useHookedOnState
is a react hook that looks and functions similar to the useState
hook. The only difference is it allows you to update a Redux store instead of local component state by specifying a slice of the global state to modify along with a default value in case nothing is there.
const Counter = props => {
const [count, setCount] = useHookedOnState('app.components.counterValue', 0)
return (
<main>
<p>You clicked {count} times.</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</main>
)
}
Now, whenever you use the setCount
function you defined, it will immutably update the Redux store to look like:
{
app: {
components: {
counterValue: 1
}
}
}
You can update any slice of the global state this way by providing a path as the first parameter of useHookedOnState
. The path string parameter works identically to lodash's _.set
.
API
createHookedOnReducer
createHookedOnReducer(initialState, namespace, handlers)
Creates a Redux reducer meant to be used with createStore
.
Arguments
initialState
: (any) The initial state of the slice of the Redux store controlled by the hooked-on-reducer. Use this parameter to define pre-existing state. Default value: {}
namespace
: (string) Hooked on Redux generates Redux actions behind the scenes without you having to do anything. To allow interoperability with other actions, Hooked on Redux prefixes its own actions with a string. Anything with this string will be funneled through the hooked-on-reducer this function creates. Default Value: 'HOOKED_ON_REDUX'
handlers
: (object) If you need to add your own reducers to handle complicated state transforms or leverage existing reducers in your application, you can pass them through to handlers
. For more information, see Complex Actions in redux-updeep
(which this library is built upon).
export default createHookedOnReducer(initialState, 'MY_NAMESPACE', {
'MY_NAMESPACE/COMPLEX_ACTION': (state, action) => {
return complexTransformation(state, action.payload)
}
})
Returns: (function) This function returns a function that can be used in Redux's createStore
.
useHookedOnState
useHookedOnState(selector, defaultState, options)
Arguments
selector
: (string) Takes a path string similar to what you would use in lodash's _.set
. This path specifies the "slice" of the store that you will be modifying.
defaultState
: (any) This is the default value that will be used if the "slice" of the store specified by selector
is empty. It works very similarly to useState
's default state.
options
: (object) A configuration object that may contain the following properties:
namespace
: (string) If you are using a custom namespace forcreateHookedOnReducer
then you must specify that namespace as the third parameter. If you are not using a default namespace then you can ignore this. Default Value:'HOOKED_ON_REDUX'
rootPath
: (string) If the Hooked on Redux reducer is not at the root level of your store, you must specify the subpath it exists on with this parameter. This usually happens if you integrate Hooked on Redux into a larger Redux codebase using something likecombineReducers
. For instance, if the Hooked on Redux reducer is added to the combined reducers with the namemyReducer
, thenrootPath
should bemyReducer
as well. For a nested path you may specify a path such aspath.to.my.store
.
Returns: (array) [value, updateValue]
This function returns a "tuple" much like useState
. The first array element value
is the value at the slice of state. The second element of the array updateValue
is a function that accepts a single parameter that updates the global state at the slice of state specified by selector
.
Prior Art
Hooked on Redux is inspired by (and used to leverage) updeep and redux-updeep. In particular, this article: How we reduced boilerplate and handled asynchronous actions with redux.