Last active
November 18, 2018 02:45
-
-
Save baetheus/ee94b4cb172eefeafd1ab8c13abcf77e to your computer and use it in GitHub Desktop.
A sample react hook to connect to redux without connect.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useContext, useEffect, Context, useState } from 'react'; | |
| import { Store } from 'redux'; | |
| /** | |
| * Creates a useRedux hook. | |
| * | |
| * First function takes Context. | |
| * | |
| * Second function takes a selector and an optional comparator and | |
| * returns the output of the selector and the store's dispatch function | |
| * | |
| * Updates only when comparator detects a change (by default on strict equality change) | |
| */ | |
| export const useReduxFactory = <S>(context: Context<Store<S>>) => <O>( | |
| selector: (s: S) => O, | |
| comparator: (p: O, n: O) => boolean = (p, n) => p !== n | |
| ) => { | |
| const { dispatch, subscribe, getState } = useContext(context); | |
| const [state, setState] = useState<O>(selector(getState())); | |
| const listener = () => { | |
| const nextState = selector(getState()); | |
| if (comparator(state, nextState)) { | |
| setState(nextState); | |
| } | |
| }; | |
| useEffect(() => subscribe(listener), [context, selector, comparator]); | |
| return [state, dispatch] as [typeof state, typeof dispatch]; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as React from 'react'; | |
| import { render } from 'react-dom'; | |
| import { store, StoreContext, useRedux, changeCount } from './store'; | |
| const Counter: React.SFC = () => { | |
| const [count, dispatch] = useRedux(s => s.count); | |
| const inc = () => dispatch(changeCount(c => c + 1)); | |
| const dec = () => dispatch(changeCount(c => c - 1)); | |
| return ( | |
| <section className="ba-7 ba-sm-2 ba-solid"> | |
| <h1>Count : {count}</h1> | |
| <button onClick={inc}>Increment</button> | |
| <button onClick={dec}>Decrement</button> | |
| </section> | |
| ); | |
| }; | |
| const App: React.SFC = () => ( | |
| <StoreContext.Provider value={store}> | |
| <Counter /> | |
| </StoreContext.Provider> | |
| ); | |
| const container = document.getElementById('app'); | |
| render(<App />, container); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { createContext } from 'react'; | |
| import { combineReducers, createStore } from 'redux'; | |
| import { useReduxFactory } from './useReduxFactory'; | |
| // Boilerplate Reducer, Types, and Store | |
| const interface Action<T extends string = string> { | |
| type: T; | |
| } | |
| interface CountStore { | |
| count: number; | |
| } | |
| const INITIAL_COUNT_STORE: CountStore = { | |
| count: 0; | |
| } | |
| const countReducer = (s: S, a: Action) => { | |
| switch (a.type) { | |
| case 'CHANGE_COUNT': return { ...s, count: a.payload(s.count) }; | |
| default: return s; | |
| } | |
| const changeCount = (payload: (s: number) => number) => ({ type: 'CHANGE_COUNT', payload }); | |
| // Create Store Factory | |
| const configureStore = () => { | |
| const rootReducer = combineReducers({ | |
| count: countReducer | |
| }); | |
| const store = createStore(rootReducer); | |
| const StoreContext = createContext(store); | |
| return { | |
| store, | |
| StoreContext | |
| }; | |
| }; | |
| // Create/Export Store and useRedux Hook | |
| export const { store, StoreContext } = configureStore(); | |
| export const useRedux = useReduxFactory(StoreContext); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment