diff options
Diffstat (limited to '')
| -rw-r--r-- | client/src/actions.js | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/client/src/actions.js b/client/src/actions.js new file mode 100644 index 0000000..e1a3611 --- /dev/null +++ b/client/src/actions.js @@ -0,0 +1,44 @@ +import { h, createContext } from 'preact'; +import { useRef, useState, useCallback, useContext } from 'preact/hooks'; +import { API_PREFIX } from './config'; + +export const fetchJSON = async (url, method='GET', data=undefined) => { + const res = await fetch(new URL(url, API_PREFIX).href, { + method, + credentials: 'include', + headers: { 'content-type': data && 'application/json' }, + body: data && JSON.stringify(data), + }); + + if (res.status !== 200) + throw new Error("wrong status"); + + return res.json(); +}; + +const DispatchContext = createContext((action) => { + throw new Error(`Unhandled action: ${action.type}`); +}); + +export const useDispatcher = ({ reducer, initialState }) => { + const parentDispatch = useDispatch(); + + const ref = useRef(); + const [state, setState] = useState(initialState); + ref.current = state; + + const dispatch = useCallback((action) => { + const update = reducer(action); + if (!update) return parentDispatch(action); + + return update.then(f => setState(f(ref.current))); + }, [ref, reducer]); + + return { + state, + dispatch, + DispatchProvider: ({ children }) => <DispatchContext.Provider value={dispatch} children={children} />, + }; +}; + +export const useDispatch = () => useContext(DispatchContext); |
