Skip to content

onload is not working because is getting rendered as string #202

Open
@eduardocque

Description

@eduardocque

Hi @staylor , i was testing the library and the reason why onload is not working is because is getting rendered as string instead the reference,

https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute#value (check this one for references)

checking the next code
src/client.ts method updateTags

for (const attribute in tag) {
        if (Object.prototype.hasOwnProperty.call(tag, attribute)) {
          if (attribute === TAG_PROPERTIES.INNER_HTML) {
            newElement.innerHTML = tag.innerHTML;
          } else if (attribute === TAG_PROPERTIES.CSS_TEXT) {
            // This seems like a CSSImportRuleDeclaration?
            // @ts-ignore
            if (newElement.styleSheet) {
              // @ts-ignore
              newElement.styleSheet.cssText = tag.cssText;
            } else {
              // @ts-ignore
              newElement.appendChild(document.createTextNode(tag.cssText));
            }
          } else {
            const attr = attribute as keyof HTMLElement;
            const value = typeof tag[attr] === 'undefined' ? '' : tag[attr];
            newElement.setAttribute(attribute, value as string);
          }
        }
      }

if we notice, onload will be added with newElement.setAttribute that one is good for strings, but if we need to pass down onload or any other event should be a direct assignation for example

newElement['onload'] = callback; // this way works and is not going to be rendered as string

in this way works perfectly, i havent make a PR due that probably you want to improve this code example

with that change we can do things like this

const fancyLoad = useCallback(e => console.log('Hello World'), []);

// JSX 
<Helmet>
  <script src="niceUrlHere" type="text/javascript" onload={fancyLoad} />
</Helmet>

probably to keep linters happy i will pass the prop as onLoad and internally rename it to onload for javascript standards

in this way we can solve it

a proposal way for the fix

for (const attribute in tag) {
        if (Object.prototype.hasOwnProperty.call(tag, attribute)) {
          if (attribute === TAG_PROPERTIES.INNER_HTML) {
            newElement.innerHTML = tag.innerHTML;
          } else if (attribute === TAG_PROPERTIES.CSS_TEXT) {
            // This seems like a CSSImportRuleDeclaration?
            // @ts-ignore
            if (newElement.styleSheet) {
              // @ts-ignore
              newElement.styleSheet.cssText = tag.cssText;
            } else {
              // @ts-ignore
              newElement.appendChild(document.createTextNode(tag.cssText));
            }
          } else if (typeof tag[attr] === 'function') {
            // Events Here (example fix) will require more tests
            const attr = attribute as keyof HTMLElement;
            const value = typeof tag[attr] === 'undefined' ? '' : tag[attr];
            newElement[attribute] = value;
          } else {
            const attr = attribute as keyof HTMLElement;
            const value = typeof tag[attr] === 'undefined' ? '' : tag[attr];
            newElement.setAttribute(attribute, value as string);
          }
        }
      }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions