Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

voidEl breaks with: $ELEMENT is a void element tag and must neither have children nor use dangerouslySetInnerHTML. #243

Open
kentcb opened this issue Jun 3, 2024 · 3 comments

Comments

@kentcb
Copy link

kentcb commented Jun 3, 2024

We recently upgraded from Fable.React 5.4.0 to 9.4.0, a rather large jump to be sure. An issue we now have is that rendering an element using either voidEl (either directly or indirectly via Fable.React.Standard) results in an error:

Uncaught Error: br is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.

Curiously, if I copy voidEl into my component and use that copy then it works. Digging a little deeper, I can see that it comes down to what JS is generated for each case. The working case generates:

react.createElement("br", {})

And the non-working case:

react.createElement("br", {}, [])

I assume the trailing empty array is triggering the error diagnostic because it is being interpreted as an attempt to assign zero children to the br, as opposed to not even attempting to assign any children.

I've got a feeling it has something to do with the ParamListAttribute on the children parameter to createElement, but not entirely sure why it manifests in one scenario and not the other.

@MangelMaxime
Copy link
Member

Hello @kentcb,

Which version of Fable are you using ?

I was trying to look into the generated code using Fable REPL and reproduction code and it doesn't seems to add the empty array when it is empty.

open Fable.Core

type ReactElement = obj

type IReactExports =
    /// Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type.
    abstract createElement: comp: obj * props: obj * [<ParamList>] children: ReactElement seq -> ReactElement
    // abstract createElement: comp: obj * props: obj -> ReactElement

let react : IReactExports = unbox null

let inline voidEl (tag: string) (props: obj seq) : ReactElement =
    react.createElement(tag, props, [])

voidEl "br" [] |> ignore

generates

import { defaultOf } from "fable-library-js/Util.js";

export const react = defaultOf();

react.createElement("br", []);

@kentcb
Copy link
Author

kentcb commented Jun 6, 2024

Hi @MangelMaxime, this was with Fable 4.18.0 which I see is still latest. I think the problem with your repro is that you've had to define voidEl yourself rather than use it indirectly through Fable.React. As I mentioned, when I defined my own copy of voidEl it worked fine - it's only when using it through Fable.React that I can reproduce the problem, as though the compiler is getting confused by the extra layer of indirection.

@MangelMaxime
Copy link
Member

Oh sorry, I misunderstood or was not focused enough.

Then, I suppose the issue is more with Fable compiler itself than this library.

I opened an issue to track it there: fable-compiler/Fable#3834

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants