首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Purescript编译但js抛出错误: component.initialState不是函数

Purescript编译但js抛出错误: component.initialState不是函数
EN

Stack Overflow用户
提问于 2021-06-10 18:58:18
回答 1查看 52关注 0票数 0

我正在使用purescript-halogen构建一个简单的视频播放器组件。该组件应该显示一个只有一个输入按钮的空白div,以供用户选择一个本地文件,然后该文件将充当视频元素的源URL。

我用纯javascript完成了一个工作模型,并想把它移植到purescript/halogen上。我得到了要编译的purescript版本,但web控制台给了我一个错误消息Uncaught TypeError: component.initialState is not a function,并将我指向这个MDN reference

这可能会提示我如何定义initialState函数的问题,但这是相当标准的:

代码语言:javascript
复制
component :: forall q i o m. MonadAff m => H.Component q i o m
component =
  H.mkComponent
    { initialState
    , render
    , eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
    }

type State =
  { videoUrl :: Maybe String }

initialState :: forall i. i -> State
initialState _ =
  { videoUrl : Nothing
  }

有没有可能函数在其生命周期中的错误时间被调用,从而使其未定义?

组件的代码托管在这个Github gist上。我一直在关注这个Github issue作为参考。

我的package.json

代码语言:javascript
复制
  "private": true,
  "devDependencies": {
    "parcel": "1.12.3",
    "purescript": "^0.14.0",
    "spago": "^0.19.1"
  },
  "scripts": {
    "build": "spago build",
    "test": "spago test",
    "serve": "parcel dev/index.html --open",
    "build-prod": "mkdir -p prod && cp dev/index.html prod/ && rm -rf dist && spago bundle-app --to prod/index.js && parcel build prod/index.html"
  },
  "dependencies": {
    "node": "^15.12.0"
  }
}

我使用purescript v0.14.0spago v0.20.0node v16.3.0进行编译,并在Ubuntu 20.04.2 LTSFirefox v89.0上进行测试。

EN

回答 1

Stack Overflow用户

发布于 2021-06-10 19:38:50

似乎这个bug来自于代码中令人讨厌的一行:

代码语言:javascript
复制
HH.input 
  [ ...
  , HP.value "Select file"
  ...]

根据MDN的说法,输入元素的value属性用于保存所选文件的路径。因此,在创建元素时设置它不是一个定义良好的操作。

最后的代码(按预期运行)是:

代码语言:javascript
复制
module App.Video (component) where

import DOM.HTML.Indexed.InputAcceptType (InputAcceptType, InputAcceptTypeAtom(..))
import Data.Foldable (traverse_)
import Data.Maybe (Maybe(..))
import Data.MediaType (MediaType(..))
import Data.Traversable (for_)
import Effect.Aff.Class (class MonadAff)
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
import Halogen.HTML.Properties as HP
import Prelude (Unit, bind, const, discard, pure, unit, ($), (=<<), (>>=))
import Web.Event.Event as Event

import Web.File.File as File
import Web.File.FileList as FileList
import Web.File.FileReader.Aff as FileReaderAff
import Web.HTML.HTMLInputElement as InputElement

data Action = HandleFileUpload Event.Event

type State =
  { videoUrl :: Maybe String }

component :: forall q i o m. MonadAff m => H.Component q i o m
component =
  H.mkComponent
    { initialState
    , render
    , eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
    }

initialState :: forall input. input -> State
initialState inp =
  { videoUrl : Nothing
  }

render :: forall m slots. State -> H.ComponentHTML Action slots m
render state =
    case state.videoUrl of
        Nothing -> blank_player
        Just url -> video_player url

supported_formats :: InputAcceptType
supported_formats = 
    HP.InputAcceptType
        [ AcceptMediaType (MediaType "video/mp4")
        , AcceptMediaType (MediaType "video/webm")
        ]

blank_player :: forall w. HH.HTML w Action
blank_player = 
    HH.div_ 
        [ HH.span_ [HH.text "Choose file to upload"]
        , HH.input
            [ HP.type_ HP.InputFile
            , HP.accept supported_formats
            , HE.onChange HandleFileUpload
            ]
    ]

video_player :: forall w i. String -> HH.HTML w i
video_player url = 
    HH.div_ [
        HH.video [HP.src url] []
    ]

handleAction :: forall m slots o. MonadAff m => Action -> H.HalogenM State Action slots o m Unit 
handleAction = case _ of
  HandleFileUpload ev → do
    traverse_ handleFileUpload (InputElement.fromEventTarget =<< Event.target ev)

handleFileUpload :: forall m slots o. MonadAff m => InputElement.HTMLInputElement -> H.HalogenM State Action slots o m Unit 
handleFileUpload inputEl = do
  H.liftEffect (InputElement.files inputEl) >>= traverse_ \files ->
    for_ (FileList.item 0 files) \file → do
      video_url ← H.liftAff $ FileReaderAff.readAsDataURL (File.toBlob file)
      H.modify_ (const { videoUrl : Just video_url})
      pure unit
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67919779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档