Skip to content

Instantly share code, notes, and snippets.

@kerams
Created May 31, 2020 11:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kerams/cc1c56ee323718d82b55b0c262f6c23f to your computer and use it in GitHub Desktop.
Save kerams/cc1c56ee323718d82b55b0c262f6c23f to your computer and use it in GitHub Desktop.
Reusable debouncer hook for F#/React/Fable based on Feliz.UseElmish
// depends on https://www.nuget.org/packages/Feliz.UseElmish
module Debouncer =
type private DebounceState<'a> = {
Value: 'a
OnDone: 'a -> unit
Delay: int }
type private Msg<'a> =
| ValueChanged of 'a
| Debounced of 'a
let private init value onDone delay =
{ Value = value; OnDone = onDone; Delay = delay }, []
let private update msg state =
match msg with
| Debounced thenValue ->
if state.Value = thenValue then
state.OnDone thenValue
state, []
| ValueChanged value ->
let a = async {
do! Async.Sleep state.Delay;
return Debounced value }
{ state with Value = value }, Cmd.OfAsyncImmediate.result a
let useDebouncer value onDone delay =
let current, dispatch = Feliz.React.useElmish (init value onDone delay, update, [||])
current.Value, (ValueChanged >> dispatch)
// Usage
// Use `onChange` to inform the debouncer about every change in the underlying input field
// When the value hasn't changed in 300ms, the debouncer will pass the current value to
// the function provided to it, dispatching a `SearchTermChanged` message to the parent
// component in this case. The actual debouncing is thus completely hidden away from the user.
let search = Feliz.React.functionComponent (fun (x: {| dispatch: Msg -> unit |}) ->
let currentValue, onChange = Debouncer.useDebouncer "" (SearchTermChanged >> x.dispatch) 300
div [] [
input [ Type "text"; Value currentValue; OnChange (fun x -> onChange x.Value) ]
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment