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

className is not correctly coerced to strings for Function proxies #390

Closed
sliftist opened this issue Aug 28, 2024 · 2 comments · Fixed by #391
Closed

className is not correctly coerced to strings for Function proxies #390

sliftist opened this issue Aug 28, 2024 · 2 comments · Fixed by #391

Comments

@sliftist
Copy link

sliftist commented Aug 28, 2024

Repro:

let classNameBuilder = new Proxy(() => {}, { get() { return () => "example-class" } })
let element = <div className={classNameBuilder} />;
// <div></div>
console.log(renderToString(element));

However, in the browser:

var element = document.createElement("div");
element.className = new Proxy(() => {}, { get() { return () => "example-class" } })
// <div class="example-class"></div>
console.log(element.outerHTML)

It looks like all attributes which are functions are ignored, when className should in fact be coerced to a string.

I only tested on Chrome, but I believe string coercion is the spec compliant behavior. The spec says that The className attribute must reflect the "class" content attribute (https://dom.spec.whatwg.org/#dom-element-classname), and it appears that in the process of doing this a string coercion is implied.

@marvinhagemeister
Copy link
Member

We have a fast bail out during attribute rendering that checks if the value is a function and bails out.

if (typeof v == 'function') continue;

It feels like a very odd way to use className. I'm curious what the situation is where one would not want to pass strings as values.

@sliftist
Copy link
Author

I use function proxies to build type-safe css for some personal projects.

It's worked well in the browser, and I only ran into problems when I started server-side rendering, due to the function attributes being ignored.

Thanks for the fast pull request! I made a similar change in a development fork, but I understand if you don't want to add the complexity into master.

By the way, the type-safe css library is here: https://www.npmjs.com/package/typesafecss, and it looks like this:

<div className={css.display("flex").gap(10)}>
    {items.map(item => <div>{item}</div>)}
</div>

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

Successfully merging a pull request may close this issue.

2 participants