1.1.2 • Published 2 years ago

react-reduce-hooks v1.1.2

Weekly downloads
4
License
MIT
Repository
github
Last release
2 years ago

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.

PropsTypeDescriptionOptional / Required
storeanyThe store value returned by useReducer or createStoreRequired
dispatchFunctionThe dispatch function returned by useReducer or createStoreRequired
contextReact Context or React Context, React Context or undefinedyour 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 functionOptional
equalityFnFunctionFunction used to compare old vs new state; by default it performs shallow equality checkOptional

createStore

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

ParamTypeDescriptionOptional / Required
reduceranyThe root reducer of your application to pass to useReducerRequired
initialStateFunctionThe initial state. It is a best practice to specify it. If optional your reducer should be able to return it when calledOptional
  • 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.

ParamTypeDescriptionOptional / Required
contextReact ContextThe 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.

ParamTypeDescriptionOptional / Required
selectorFunctionThe selector function. takes the state as param. the return will be the return value of useSelectorRequired
contextReact ContextThe 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.

ParamTypeDescriptionOptional / Required
initValueanyInitial value for the ContextRequired
  • 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.

ParamTypeDescriptionOptional / Required
contextReact ContextThe 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

1.1.1

2 years ago

1.1.0

2 years ago

1.1.2

2 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.2

4 years ago

1.0.3

4 years ago

1.0.0

4 years ago