How I found own way to access Redux in React component

in #developmentlast year (edited)

Hello, there!

I’ve seen a lot of more articles about React and Redux combination and most of them explaining how to connect these solutions and basic usage. But lets imagine that We have a project a bit larger than the regular todo-list example. Our project have a store with a lot of different modules and hundreds actions.

I would like to show You how I created my own solution without any built-in solutions or packages.

Trivial solutions

Props way

The most trivial and easy solution is a providing a store state and actions via props. I won’t describe a full example here You know how it works.

connect(mapStateToProps, (dispatch: Dispatch<AnyAction>) =>
  bindActionCreators({<actions_object>}, dispatch))(MyComponent)

Pros: Easy to use, fast solution, reactive as well.
Cons: Need to provide each store state item or action manually to a child component(Of course, You may connect each component to the store but there will be a very high-weight components).

Built-in hooks way

Latest versions of Redux offers us several hooks for accessing to store like:

  1. useStore — get the store instance directly;
  2. useDispatch — get a dispatch function;
  3. useSelector — build a reactive getter from store;
    Pros: Easy to use, fast, partial reactive;
    Cons: useStore isn’t reactive at all – You may get a state but it will be the snapshot only – not applicable. useSelector isn’t convenient to get a lot of data. You may try to select the whole state and destruct gotten object but it will return the new value each time when main state will be changed. It may cause unexpected behavior.

My solution

Let’s start with a defining of what we need. I would like to make a hook which will allow getting any state module, property as reactive and getting any action. It should support TypeScript as well, obviously.

Actually, we have to remember about performance and convenience. So, let’s see how it should be used:

const { someState, someAction } = ourHook() // someState and someAction provide types automatically

Let’s start with creating of custom hook.

const useMappedStore = () => {
  return {...state, ...actions}; // Typed
}

Firstly, I have to map the store actions, make them dispatchable and return to component. It could be achieved with the built-in redux function bindActionCreators(actionsObj, dispatch).

Secondly, need to get store state reactively. We may achieve it with hooks above. But how we can get a state dynamically and reactively?
Let’s use a one interest instrument named as Proxy.

export const useMappedStore = () => {
  const store = useStore<AppState>();
  const dispatch = useDispatch();

  const storeStateAccessor: AppState = store.getState();
  const storeStateAccessorProxy = new Proxy<AppState>(storeStateAccessor, {
    get(target, p, receiver) {
      return useSelector((state) => state[p]);
    }
  });

  return {
    ...storeStateAccessorProxy,
    ...bindActionCreators(getActions(), dispatch)
  };
};

As you can see I used a proxy to creating a selector hook dynamically. Any store state property will be called when component will be created. Pay attention we are not breaking hooks rules.

If We have to support old browsers We could use Object.defineProperty as well.

Instead of conclusion

I know NPM has a thousands redux helper packages and I just wanted to show you how developer could implement it manually.
Thanks for reading!

Source article: Link
Source code: GitHub

Sort:  

Congratulations @vicev1! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)

You received more than 50 upvotes.
Your next target is to reach 100 upvotes.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out our last posts:

Hive Power Up Day - November 1st 2023