aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/actions.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--client/src/actions.js44
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);