Skip to content

Instantly share code, notes, and snippets.

@donut
Last active June 10, 2019 18:43
Show Gist options
  • Save donut/4a62ac83887b140cd131c8c2bbdcdb6a to your computer and use it in GitHub Desktop.
Save donut/4a62ac83887b140cd131c8c2bbdcdb6a to your computer and use it in GitHub Desktop.
A wrapper for React's useReducer() hook that applies middleware. Written in OCaml.
let use_reducer ?(middleware=[]) reducer initial =
(* [middlewared_dispatch] is setup as a reference so we can change it to the
dispatch function returned by [useReducer]. This way we can insert
middleware before the real reducer function runs. *)
let middlewared_dispatch = React.useRef (fun a ->
Js.Console.error2 "Dispatch called before reducer hook initialized." a)
in
let apply_middleware middleware state action =
let dispatch = React.Ref.current middlewared_dispatch in
let rec apply action = function
| [] -> action
| hd :: tl ->
match hd ~dispatch state action with
| `Rerun a -> apply a middleware
| `Next a -> apply a tl
| `Stop a -> a
in
apply action middleware
in
let middlewared_reducer state action =
action
|> apply_middleware middleware state
|> reducer state
in
let state, dispatch = React.useReducer middlewared_reducer initial in
React.Ref.setCurrent middlewared_dispatch dispatch;
(state, dispatch)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment