Redux middleware compatible React Hooks library for easy global state management

语言: CN / TW / HK

The library

I’ve been developing a library to make use of React Hooks API. The library is for global state mangement with the aim to use it instead of Redux, especially for smaller applications. See the repository for more information and the source code.

Please also check out my previous posts [1] [2].

Support for Redux middleware

Originally, the library was extending useState for global state. Later, reducer is supported. Now, middleware support is added. The following is the code snippet from the working example to illustrate how it can be used.

At first, we import createStore from our library and two helpers from Redux.

import { createStore } from 'react-hooks-global-state';
import { applyMiddleware, combineReducers } from 'redux';

We then define the initial state. Note, the initial state is mandatory in our library, whare as it’s optional in Redux.

const initialState = {
  counter: 0,
  person: {
    age: 0,
    firstName: '',
    lastName: '',
  },
};

We define two reducers for each state items ( counter and person ).

const counterReducer = (state = initialState.counter, action) => {
  switch (action.type) {
    case 'increment': return state + 1;
    case 'decrement': return state - 1;
    default: return state;
  }
};
const personReducer = (state = initialState.person, action) => {
  switch (action.type) {
    case 'setFirstName': return {
      ...state,
      firstName: action.firstName,
    };
    case 'setLastName': return {
      ...state,
      lastName: action.lastName,
    };
    case 'setAge': return {
      ...state,
      age: action.age,
    };
    default: return state;
  }
};

Then, combine them with combineReducers .

const reducer = combineReducers({
  counter: counterReducer,
  person: personReducer,
});

We define logging middleware which is from the Redux documentation.

const logger = ({ getState }) => next => (action) => {
  console.log('will dispatch', action);
  const returnValue = next(action);
  console.log('state after dispatch', getState());
  return returnValue;
};

We create a store based on what we defined above.

const { dispatch, stateItemHooks } = createStore(
  reducer,
  initialState,
  applyMiddleware(logger),
);

Finally, we export functions so that components can use them if needed. The way hooks are destructured and exported is not very common at this point. To my knowledge, this is a reasonable way to allow type inference for TypeScript, but if there’s a better way, it’s considerable.

export const {
  counter: useGlobalStateCounter,
  person: useGlobalStatePerson,
} = stateItemHooks;

export { dispatch };

For example the counter component is implemented like the following.

const Counter = () => {
  const [value] = useGlobalStateCounter();
  return (
    <div>
      <span>Count: {value}</span>
      <button
        type="button"
        onClick={() => dispatch({ type: 'increment' })}
      >
        Increment
      </button>
    </div>
  );
};

The full example code in TypeScript

You can see the full example code in the repository . It is written in TypeScript, but JavaScript developers could read it by just ignoring type definisions ( type Foo = ...; ) and type annotations ( : Foo just after variables).

It’s working but more experiments are needed

As far as I tried, the logger middleware works as expected. I haven’t tried other middleware yet. Especially, async libraries should be tried. If anybody is interested in trying some other middleware, I’d be happy to help.

A final note

React 16.7 which will introduce the Hooks API is not yet released. Until it’s official, anything that relies on hooks should be experimental. But, you’ve got to try it anyway.

分享到: