Как создать собственный компонент React в Fable? - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь написать простой компонент React, используя Fable. Должен отображаться простой счетчик с кнопками + и -. Он также принимает сообщение string через реквизит.

Что неожиданно, так это то, что код компилируется, но выдает ошибку времени выполнения:

Ошибка: объекты недопустимы как дочерний элемент React (найдено: объект с ключами { реквизиты, контекст, ссылки, обновления, состояние}).

Если вы намеревались визуализировать коллекцию дочерних элементов, используйте вместо этого массив.

Вот код:

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 (а не крючки или Elmi sh) по разным причинам.

1 Ответ

2 голосов
/ 28 февраля 2020

В вашей функции 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 ()
...