Alternative `ReactRedux.connect()` by `useContext()` for performance.
npm install use-react-redux-contextAlternative ReactRedux.connect() by useContext() for performance.
``bash`peer deps
$ yarn add react react-dom redux react-redux
$ yarn add use-react-redux-contextor npm install --save use-react-redux-context
yarn add @types/react @types/redux @types/react-redux -D # for typescript
- Pre-defined connected React.Context with mapState (no own props)
- Create bound actions by useCallback
- Emit render by shallow equal comparation
- TypeScript friendly
of react-redux@6Just React.useContext(ReactReduxContext) emits rendering by all state update. Pre-defined contexts and reducers are good for performance.
And I don't know good ownProps usages on ReactRedux.connect.
Minimum conceptual code
`tsx
import { Provider as ContextProvider, Scope } from "use-react-redux-context";
import { Provider as ReactReduxProvider } from "react-redux";
const scope = new Scope();
const RootStateContext = scope.createContext(s => s);
const All = () => {
const all = useContext(RootStateContext);
return
{JSON.stringify(all)};const store = createStore(reducer); // create your reducer
const el = (
);
`
Working code
`tsx
import React, { useContext, useCallback, useEffect } from "react";
import ReactDOM from "react-dom";
import { createStore, combineReducers, Reducer } from "redux";
import { Provider as ReactReduxProvider } from "react-redux";
import { Provider as ContextProvider, Scope } from "use-react-redux-context";
// Write your own reducer
type Foo = {
value: number;
};
type RootState = {
foo: Foo;
};
type IncrementAction = { type: "increment" };
type Action = IncrementAction;
function foo(state: Foo = { value: 0 }, action: Action): Foo {
switch (action.type) {
case "increment": {
return { value: state.value + 1 };
}
default: {
return state;
}
}
}
function increment(): IncrementAction {
return { type: "increment" };
}
// Build connected React.Context
const scope = new Scope
const FooContext = scope.createContext((state, dispatch) => {
// this useCallback is under NewContext rendering hook context
const inc = useCallback(() => dispatch(increment()), []);
// emit render by shallow equal comparation
return { ...state.foo, inc };
});
function Counter() {
// This is React.useContext, not library function
const foo = useContext(FooContext);
return (
const rootReducer: Reducer
const store = createStore(rootReducer);
function App() {
return (
// Provider expand all scope's context
);
}
// @ts-ignore
ReactDOM.render(
`
Get store.dispatch Function
`tsx`
import { useDispatch } from "use-react-redux-context";
function X() {
const dispatch = useDispatch();
return (
);
}
Create function by action and actionMap (with useCallback and its memoizedKeys)
`tsx
import { useBindAction, useBindActions } from "use-react-redux-context";
const A = scope.createContext(state => {
const inc = useBindAction(increment);
// with memoized keys
// const inc = useBindAction(() => ({type: 'increment', payload: state.value}), [state.value]);
return { ...state.a, inc };
});
const B = scope.createContext(_state => {
const actions = useBindActions({ increment, decrement });
// alternative: with memoized keys map
// const actions = useBindActions({ increment, decrement }, { increment: [state.value] });
// recommend spreading for shallow equal
return { ...actions };
});
`
- yarn build: Build index.jsyarn test
- : Run jestyarn demo
- : Start application server on http://localhost:1234yarn demo:deploy`: Deploy to netlify (need netlify account)
-
MIT