npm.io
1.1.2 • Published 3 years ago

react-reduce-hooks

Licence
MIT
Version
1.1.2
Deps
1
Size
52 kB
Vulns
0
Weekly
0

react-reduce-hooks

NPM npm

Install

npm install --save react-reduce-hooks

Description

react-reduce-hooks allows you to implement a state-management solution using React Context, while leverages good practices and provide DRY code.

This is a light library and is just a simple wrapper around Context and takes ideas and patterns from redux hooks with almost the same API so you can migrate easily.

It enforces good practices for implementing state-management with hooks; e.g.:

  • Provides custom Provider HOC for wrapping your components.
  • Provides custom useSelector hook for selecting what you need from the store.
  • Prevents unnecessary re-renders implementing basic memoization on top of your components. This package uses use-context-selector internally. use-context-selector allows selecting from Context only what you need and then trigger a re-render on consumer components only when that data changes.

Why?

While it is possible to implement a simple redux-like functionality just with useReducer + useContext, there are good recommendations and practices to follow, especially for growing applications.

Since Context rerenders all the consumers using a good selector library is a must if you care about performance.

I recommend use-context-selector and this library is based on it.

This library allows you implementing good practices for your custom state-management solution using React Context while being able to migrate easily to redux if you need to.

How

In this section, we will review the basic functionality provided by the library. The snippets are based on the example application located in examples/counter.

Let's go through this example by explaining what is happening on the different files:

Provider
/// store.js

import React from 'react'
import { createStore, Provider } from 'react-reduce-hooks'

const initialState = {
  count: 0,
  name: 'world'
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return {
        ...state,
        count: state.count + 1
      }
    case 'DECREMENT':
      return {
        ...state,
        count: state.count - 1
      }
    case 'SET_NAME':
      return {
        ...state,
        name: action.name
      }
    default:
      return state
  }
}

const AppProvider = ({ children }) => {
  const [store, dispatch] = createStore(reducer, initialState)
  return (
    <Provider store={store} dispatch={dispatch}>
      {children}
    </Provider>
  )
}

export { AppProvider }

Note: you can check below the documentation for more advanced scenarios.

createStore is same as calling useReducer. After just pass the store and the dispatch function to your provider.

Next, use the Provider component for wrapping your application's code.

/// App.js

import React from 'react'
import { AppProvider } from './store'
import Counter from './Counter'
import User from './User'
import './App.css'

const App = () => (
  <AppProvider>
    <Counter />
    <User />
  </AppProvider>
)

export default App

Now you just subscribe to state changes with useSelector and dispatch actions in your components.

/// Counter.js

import React from 'react'
import { useSelector, useDispatch } from 'react-reduce-hooks'

const Counter = () => {
  const count = useSelector((state) => state.count)
  const dispatch = useDispatch()
  return (
    <p>
      Clicked: <span>{count}</span> times
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </p>
  )
}

export default Counter

Same here.

/// User.js

import React, { useRef } from 'react'
import { useSelector, useDispatch } from 'react-reduce-hooks'

const User = () => {
  const name = useSelector((state) => state.name)
  const dispatch = useDispatch()
  const inputRef = useRef()
  return (
    <p>
      Hello <span>{name}</span> <input ref={inputRef} autoFocus={true} />
      <button onClick={() => dispatch({ type: 'SET_NAME', name: inputRef.current.value })}>set name</button>
    </p>
  )
}

export default User

Documentation

Provider

The provider component to wrap your application.

Props Type Description Optional / Required
store any The store value returned by useReducer or createStore Required
dispatch Function The dispatch function returned by useReducer or createStore Required
context React Context or [React Context, React Context or undefined] your custom context if you want to hold the reference. it can be an array of two Contexts, the first for your state the second for the dispatch function Optional
equalityFn Function Function used to compare old vs new state; by default it performs shallow equality check Optional
createStore

The same as useReducer. It is just a wrapper around it

Param Type Description Optional / Required
reducer any The root reducer of your application to pass to useReducer Required
initialState Function The initial state. It is a best practice to specify it. If optional your reducer should be able to return it when called Optional
  • Return Value: an array with first argument the store and second argument the dispatch function
useDispatch

This hook is used to get the dispacth function on your components.

Param Type Description Optional / Required
context React Context The dispatch Context that you've passed to the provider in the context props as second element of the array. This is the case when you hold the reference of your own contexts. Optional
  • Return Value: the dispatch function
useSelector

This hook is used to access the state.

Param Type Description Optional / Required
selector Function The selector function. takes the state as param. the return will be the return value of useSelector Required
context React Context The state Context that you've passed to the provider in the context props as first element of the array. This is the case when you hold the reference of your own contexts. Optional
  • Return Value: the value returned by the selector function
createContext

Creates a smart Context object which compares changes on your Context state and dispatches changes to subscribers. This function is from the library use-context-selector.

Param Type Description Optional / Required
initValue any Initial value for the Context Required
  • Return Value: Context
useStore

This hook is not very useful. It's the same as calling React's useContext. It gives you the context value.

Param Type Description Optional / Required
context React Context The state Context that you've passed to the provider in the context props as first element of the array. This is the case when you hold the reference of your own contexts. Optional
  • Return Value: Context value

Example

Check the example to better understand the library and get inspiration to write your next awesome app!

  • Counter App

This is a simple Counter application; it uses a reducer to manage state and connects components to the store using the hooks helpers.

https://github.com/pacobabs/react-reduce-hooks/tree/master/examples/counter

Problems or Suggestions

Please feel free to open an issue on github.

Devtools

For integration with devtools check my other library reduce-devtools-extension

Keywords