aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/actions.js
blob: e1a3611d07a679bda4464d841be9ba6a83e1cb73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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);