DEV Community

loading...

useRedux hook

Dani Akash πŸ§ͺπŸ’₯
A React Developer who builds open source libraries for fun. You might actually like them! πŸ˜‰
・Updated on ・2 min read

Tl;dr
useRedux hook connects your react component directly to the redux store using a single hook. You can check out the project at οΉ£

GitHub logo react-native-toolkit / useRedux

Hook to connect redux store to react components

useRedux πŸͺ

Hook to connect redux store to react components

Build Status Maintainability Test Coverage

Version Downloads Bundlephobia

Star on GitHub Watch on GitHub Twitter Follow

donate sponsor support

PRs Welcome πŸ‘βœ¨

Motivation

The goal of this library is to provide a simple API to connect your React components to the Redux store. It achieves this by using a single hook useRedux that subscribes to the state updates in redux store without any need for the traditional Provider or connect components.

Installation

yarn add @daniakash/useredux
#or
npm i @daniakash/useredux
Enter fullscreen mode Exit fullscreen mode

Usage

Redux store of a simple counter οΉ£

import { createStore } from 'redux'
const countReducer = (
  prevState = 0,
  action: { type: 'increment' | 'decrement' }
): number => {
  switch (action.type) {
    case 'increment':
      return prevState + 1

    case 'decrement':
      return prevState - 1

    default:
      return prevState
  }
}

const countStore = createStore(countReducer)

export default countStore
Enter fullscreen mode Exit fullscreen mode

Connecting the countStore to React…

Update:-

  • This hook is under development & I'm currently collecting feedbacks from the community. Let me know your thoughts after reading this post.
  • Currently importing the store directly into the react components breaks the redux style guide (only one redux store per app). A future update will fix this problem.

I like using Redux. It is an excellent state management tool that gives us full control over how the state is modified. However, I always find it a tedious process to set up react-redux to connect every single component to redux.

Which is why I decided to build a simpler way to connect my redux store to react component.

Redux stores contain a subscription API οΉ£

store.subscribe(() => {
  console.log(store.getState()); // current state
})
Enter fullscreen mode Exit fullscreen mode

So I decided to build a hook that'll update the react state whenever the store update happens οΉ£

const useRedux = (store) => {
  const [state, setState] = useState(() => store.getState())

  useEffect(() => {
    const unsubscribe = store.subscribe(() => setState(store.getState()))

    return () => unsubscribe()
  }, [store])

  return state
}
Enter fullscreen mode Exit fullscreen mode

This hook will re-render the component whenever the redux store gets updated.

const count = useRedux(countStore)
Enter fullscreen mode Exit fullscreen mode

Store with multiple reducers

What if your redux store has multiple reducers & you want components to re-render only when the reducers they depend on updates...

The following is a redux store that uses two reducers οΉ£

const rootReducer = combineReducers({
  todos: todosReducer,
  visibilityFilter: visibilityFilterReducer
})

const store: Store<ApplicationState> = createStore(rootReducer)
Enter fullscreen mode Exit fullscreen mode

This time I have to add some condition that'd ensure the state is updated only when the required part of store changes.

  // your component only depends on "todos" `key` of the store

  useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      // only get the required part of state
      const nextState = key ? store.getState()[key] : store.getState()
      // check if new state is different from the last state
      if (state !== nextState) {
        setState(nextState)
      }
    })
    return () => {
      unsubscribe()
    }
  }, [store, key, state])
Enter fullscreen mode Exit fullscreen mode

With this logic in place, your component can now subscribe to state updates that only happen on the required part of the state οΉ£

const todos = useRedux(store, 'todos')
Enter fullscreen mode Exit fullscreen mode

This hook is greatly simplifying my work while creating React Components. You can try the working example here οΉ£

This hook is available to try now, install the following packages & try it in your redux project!

yarn add @daniakash/useredux

#or

npm i @daniakash/useredux
Enter fullscreen mode Exit fullscreen mode

Looking forward to hear your thoughts on the library ✌🏽

Discussion (2)

Collapse
markerikson profile image
Mark Erikson

(copying from the Reddit thread for visibility)

I appreciate that you took the time to make this, but this is missing all of the considerable optimization work that's gone into our official useSelector hook.

Also, you should not import the store directly into components!.

This hook should definitely not be used in production.

Collapse
dani_akash_ profile image
Dani Akash πŸ§ͺπŸ’₯ Author • Edited

(copying from the Reddit thread for visibility)

I was going through the optimizations in useSelector and also in Zustand. I have a pretty good understanding of the optimization part now. Not sure how to implement the style guide since it requires use of a Provider πŸ€”πŸ˜΅

Thanks for your valuable feedback. I'll improve upon this πŸ‘

Have also updated the post with your points