I was trying to insert a component via <script>
tag but that wasn’t working. Upon reducing to the minimal testcase I found weird behavior: when a <script>
tag is created from react-basic-hooks
it’s never executed. From my findings on JS-related posts, inserting a <script>
always executes it, so this is very weird.
Here’s a minimal example:
- Create
index.html
as<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="root"></div>
<script src="index.js"></script>
</body>
</html>
- Put this code to
src/Main.purs
module Main where
import Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Exception (throw)
import React.Basic.DOM as R
import React.Basic.DOM.Client (createRoot, renderRoot)
import React.Basic.Hooks (Component, component)
import Web.DOM.NonElementParentNode (getElementById)
import Web.HTML (window)
import Web.HTML.HTMLDocument (toNonElementParentNode)
import Web.HTML.Window (document)
main :: Effect Unit
main = do
doc <- document =<< window
root <- getElementById "root" $ toNonElementParentNode doc
case root of
Nothing -> throw "Could not find root."
Just container -> do
reactRoot <- createRoot container
app <- myComponent
renderRoot reactRoot (app {})
myComponent :: Component {}
myComponent =
component "Test" \_ -> React.do
pure $ R.script {children: [R.text "alert(1)"]}
- Build it with
spago bundle-app
- Open
index.html
in a browser
Expected
An alert should pop up
Actual
No popups appear
1 Like
Actually, I just realized this doesn’t look like expected behavior and most likely a bug, so it’s best to be reported to the react-basic-hook
project directly. So I created an issue there.
As found by Pete Murphy on the linked issue, it turns out to be upstream JS React bug. There is a workaround though through re-declaring script
manually with botched letter case.
Solution for the example code:
module Main where
import Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Exception (throw)
import Effect.Unsafe (unsafePerformEffect)
import React.Basic (JSX, element)
import React.Basic.DOM as R
import React.Basic.DOM.Client (createRoot, renderRoot)
import React.Basic.Hooks (Component, component)
import Unsafe.Coerce (unsafeCoerce)
import Web.DOM.NonElementParentNode (getElementById)
import Web.HTML (window)
import Web.HTML.HTMLDocument (toNonElementParentNode)
import Web.HTML.Window (document)
-- Creates <script> tag, but works around JS React bug that <script> doesn't get
-- executed https://github.com/facebook/react/issues/19865
rScriptEval :: forall attrs. Record attrs -> JSX
rScriptEval = element (unsafeCoerce (unsafePerformEffect (R.unsafeCreateDOMComponent "sCript")))
main :: Effect Unit
main = do
doc <- document =<< window
root <- getElementById "root" $ toNonElementParentNode doc
case root of
Nothing -> throw "Could not find root."
Just container -> do
reactRoot <- createRoot container
app <- myComponent
renderRoot reactRoot (app {})
myComponent :: Component {}
myComponent =
component "Test" \_ -> React.do
pure $ rScriptEval {children: [R.text "alert(1)"]}
2 Likes