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



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

我用简单的javascript完成了一个工作模型,并希望将其移植到purescript/harum。我得到了要编译的purescript版本,但web控制台给了我一条错误消息Uncaught TypeError: component.initialState is not a function,并将我指向这个MDN引用。

这表明我如何定义initialState函数存在问题,但它相当标准:

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要点上。我一直在关注这个Github问题作为参考。

我的package.json:


"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 LTS中的Firefox v89.0上进行测试。

似乎错误来自代码中的一行:

HH.input 
[ ...
, HP.value "Select file"
...]

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

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

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

最新更新