简体   繁体   中英

How do you createRef in Suave Fable?

I have a text input, and I've managed to debounce input. However, my keypress listener won't wait for text input events to flush before processing the enter key which would end edits without getting the latest value in the uncontrolled component.

Since I'm in webpack, React... is undefined so I can't just React.createRef() The current source code shows the function exists https://github.com/fable-compiler/fable-react/blob/e904add886bab45003c074cd2b06b8834fddf65b/src/Fable.React.Helpers.fs#L366

However it doesn't resolve/compile. paket.lock shows Fable.React 4.1.3, Fable.Elmish.React 2.1.

createRef is available only since version 5.x something so you need to update to latest version. To be sure, I encourage you to upgrade to the latest version at the time of writing 5.2.3 .

This means you will need to upgrade your application to Fable.Core v3, you can read more about it here .

When done you can use createRef like that:

open Fable.React
open Fable.React.Props

type MapComponent(initProps) =
    inherit Fable.React.Component<MapComponentProps, obj>(initProps)

    let mapRef : IRefHook<Browser.Types.HTMLDivElement option> = createRef None

    override this.render() =
        div [ RefValue mapRef ]
            [ str "..." ]

As it turned out, for what I needed, the ref wasn't necessary, however I did get one going.

type IReactRef =
  inherit Browser.Element

[<Emit("React.createRef")>]
let createRef(): IReactRef = jsNative

type TextInputProps =
  { Ident: string
    Delay: int
    AddedAttributes: IHTMLProp list
    DefaultValue: string option
    OnChange: (string -> unit)
    OnEscape: (unit -> unit) option
    OnEnter: (string -> unit) option
  }

type TextInputState = InputState
let textInputDelayDefault = 500
type TextInputComponent(props) =
  inherit React.Component<TextInputProps, TextInputState>(props)
  let mutable textInput: obj = null
  let debouncer = Eventing.Debouncer<string>.Create props.Ident props.Delay

  do
    textInput <- react.createRef()
    base.setInitState InputState

  member __.TextInput: IReactRef option =
    textInput
    |> Option.ofObj
    |> Option.map unbox

  // provide cancel edit extension point (Escape doesn't fire keypress)
  member this.OnKeyUp(e: React.KeyboardEvent) =
    if e.key = "Escape" then
      match this.props.OnEscape with
      | Some f ->
        e.preventDefault()
        f()
      | None -> ()

  // provide finish edit extension point
  member this.OnKeyPress(e: React.KeyboardEvent) =
    let value =
      e
      |> unbox
      |> Eventing.getTargetValue
    if e.key = "Enter" then
      this.props.OnEnter
      |> Option.iter (fun f ->
           e.preventDefault()
           debouncer.Clear()
           // send the current value in case the onChange did not send the current value due to debouncing
           f value)

  override this.render() =
    let r =
      input [ yield R.Props.Ref(unbox textInput)
              yield R.Props.OnKeyPress this.OnKeyPress
              yield R.Props.OnKeyUp this.OnKeyUp
              yield Eventing.onDebChange debouncer this.props.OnChange
              yield R.Props.DefaultValue(this.props.DefaultValue |> Option.defaultValue "")
              yield! this.props.AddedAttributes ]
    r

let inline textInputComponent props = Fable.Helpers.React.ofType<TextInputComponent, _, _> props []

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM