如何在 Fable 中实例化一个自定义的 React 组件?
How to instantiate a custom React Component in Fable?
我正在尝试使用 Fable 编写一个简单的 React 组件。它应该显示一个带有 +
和 -
按钮的简单计数器。它还通过 props.
接收消息 string
出乎意料的是代码编译通过了,但是它抛出了 运行 时间错误:
Error: Objects are not valid as a React child (found: object with keys {props, context, refs, updater, state}).
If you meant to render a collection of children, use an array instead.
代码如下:
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
(而不是 hooks 或 Elmish)。
在您的 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 "+" ]
最后,也把你的道具改成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 ()
我正在尝试使用 Fable 编写一个简单的 React 组件。它应该显示一个带有 +
和 -
按钮的简单计数器。它还通过 props.
string
出乎意料的是代码编译通过了,但是它抛出了 运行 时间错误:
Error: Objects are not valid as a React child (found: object with keys {props, context, refs, updater, state}).
If you meant to render a collection of children, use an array instead.
代码如下:
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
(而不是 hooks 或 Elmish)。
在您的 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 "+" ]
最后,也把你的道具改成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 ()