【问题标题】:How to instantiate a custom React Component in Fable?如何在 Fable 中实例化自定义 React 组件?
【发布时间】:2020-02-26 14:47:20
【问题描述】:

我正在尝试使用 Fable 编写一个简单的 React 组件。它应该显示一个带有+- 按钮的简单计数器。它还通过 props 接收消息string

出乎意料的是,代码编译成功了,却抛出了运行时错误:

错误:对象作为 React 子对象无效(找到:带有键 {props, context, refs, updater, state} 的对象)。

如果您打算渲染一组子项,请改用数组。

代码如下:

module App

open Fable.Core
open Fable.Core.JsInterop
open Fable.React
open Browser
open Browser.Types

type App (message) =
  inherit Component<string, int> (message) with

    do
      base.setInitState(0)

    override this.render () =
      div
        []
        [
          h1 [] [ str (sprintf "%s - %i" this.props this.state) ]
          button [ Props.OnClick (fun _ -> this.setState (fun s _ -> s + 1)) ] [ str "+" ]
          button [ Props.OnClick (fun _ -> this.setState (fun s _ -> s - 1)) ] [ str "-" ]
        ]


let render () =
  ReactDom.render(
    App "Counter",
    document.getElementById "root")

render ()

我的paket.lock

STORAGE: NONE
RESTRICTION: || (== netcoreapp3.1) (== netstandard2.0) (== netstandard2.1)
NUGET
  remote: https://api.nuget.org/v3/index.json
    Fable.Browser.Blob (1.1)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.6.2)
    Fable.Browser.Dom (1.1)
      Fable.Browser.Blob (>= 1.1)
      Fable.Browser.Event (>= 1.0)
      Fable.Browser.WebStorage (>= 1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.6.2)
    Fable.Browser.Event (1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.5.2)
    Fable.Browser.WebStorage (1.0)
      Fable.Browser.Event (>= 1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.5.2)
    Fable.Core (3.1.5)
      FSharp.Core (>= 4.7)
    Fable.React (5.3.6)
      Fable.Browser.Dom (>= 1.0)
      Fable.Core (>= 3.0)
      FSharp.Core (>= 4.7)
    FSharp.Core (4.7)

注意:出于各种原因,我想使用 setState(而不是 hooksElmish)。

【问题讨论】:

    标签: reactjs f# fable


    【解决方案1】:

    在您的render 函数中,您需要像这样使用ofType

    let render () =
      ReactDom.render(
        ofType<App,_,_> "Counter" [],
        document.getElementById "root")
    

    这会渲染一些东西,但是当你点击按钮时什么也没有发生。

    要解决此问题,请将您的状态从 int 更改为 object

    type state = { count: int }
    //..
    button [ Props.OnClick (fun _ -> this.setState (fun s _ -> { s with count = s.count + 1 })) ] [ str "+" ]
    

    最后,将你的 props 更改为 object

    总而言之,以下应该有效:

    type props = { message: string }
    type state = { count: int }
    
    type App (props) =
      inherit Component<props, state> (props) with
    
        do
          base.setInitState({ count = 0 })
    
        override this.render () =
          div
            []
            [
              h1 [] [ str (sprintf "%s - %i" this.props.message this.state.count) ]
              button [ Props.OnClick (fun _ -> this.setState (fun s _ -> { s with count = s.count + 1 })) ] [ str "+" ]
              button [ Props.OnClick (fun _ -> this.setState (fun s _ -> { s with count = s.count - 1 })) ] [ str "-" ]
            ]
    
    
    let render () =
      ReactDom.render(
        ofType<App,_,_> { message = "Counter" } [],
        document.getElementById "root")
    
    render ()
    

    您可以将 ofType 调用包装在一个便利函数中:

    let inline app props children = 
      ofType<App,_,_> props children
    
    let render () =
      ReactDom.render(
        app { message = "Counter" } [],
        document.getElementById "root")
        
    render ()
    

    【讨论】:

      猜你喜欢
      • 2019-06-24
      • 2021-10-14
      • 2020-05-25
      • 2016-11-27
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多