Last active
October 3, 2022 12:53
-
-
Save amsterdamharu/33f0fa989027328fe753589819b9db8e to your computer and use it in GitHub Desktop.
Simple implementation of Redux
This file contains 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
const createSelectObservable = (() => { | |
let state; | |
let pReducer = (state, action) => state; | |
const subscribers = new Map(); | |
const addSubscriber = (selector) => { | |
subscribers.set(selector, selector); | |
//return unsubscribe function | |
return () => subscribers.delete(selector); | |
}; | |
const dispatch = (action) => { | |
state = pReducer(state, action); | |
subscribers.forEach((subscriber) => subscriber(state)); | |
}; | |
const getState = () => state; | |
return (reducer, initialState) => { | |
pReducer = reducer; | |
state = initialState; | |
return { addSubscriber, dispatch, getState }; | |
}; | |
})(); //IIFE | |
//createSelectObservable used in custom hook | |
const COUNTERS = 1000; | |
const ADD = 'COUNTERS_ADD'; | |
const REMOVE = 'COUNTERS_REMOVE'; | |
const initialState = Object.fromEntries( | |
[...new Array(COUNTERS)].map((_, index) => [index, 0]) | |
); | |
const reducer = (state, { type, payload }) => { | |
if (type === ADD) { | |
return { | |
...state, | |
[payload]: state[payload] + 1, | |
}; | |
} | |
if (type === REMOVE) { | |
const { [payload]: gone, ...rest } = state; | |
return rest; | |
} | |
return state; | |
}; | |
const { addSubscriber, dispatch, getState } = | |
createSelectObservable(reducer, initialState); | |
const useCounter = (selector) => { | |
const [state, setState] = useState(selector(getState())); | |
useEffect( | |
() => | |
addSubscriber((state) => setState(selector(state))), | |
[selector] | |
); | |
return state; | |
}; | |
//components using the state | |
const Component = () => { | |
const counters = useCounter((s) => s); | |
return ( | |
<ul> | |
{Object.entries(counters).map(([id, count]) => ( | |
<Counter key={id} id={id} /> | |
))} | |
</ul> | |
); | |
}; | |
const Counter = React.memo(function Counter({ id }) { | |
const add = () => dispatch({ type: ADD, payload: id }); | |
const remove = () => | |
dispatch({ type: REMOVE, payload: id }); | |
const selector = useCallback((state) => state[id], [id]); | |
const count = useCounter(selector); | |
return ( | |
<li> | |
{id}: <button onClick={add}>{count}</button> | |
<button onClick={remove}>remove</button> | |
</li> | |
); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment