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

TypeError: tag[primaryAttributeKey].toLowerCase is not a function with external scripts in reactjs without gatsby #448

Open
Way-U-Need opened this issue Mar 18, 2019 · 11 comments

Comments

@Way-U-Need
Copy link

Way-U-Need commented Mar 18, 2019

please help me out from this error:
`TypeError: tag[primaryAttributeKey].toLowerCase is not a function
(anonymous function)
node_modules/react-helmet/lib/HelmetUtils.js:141
138 | return false;
139 | }
140 |

141 | var value = tag[primaryAttributeKey].toLowerCase();
| ^ 142 |
143 | if (!approvedSeenTags[primaryAttributeKey]) {
144 | approvedSeenTags[primaryAttributeKey] = {};`

used external javascripts for some animations and css change.

code :
import inspinia from "./assets/js/inspinia" class App extends Component { render() { return ( <> <Helmet> <script src={inspinia} type="text/javascript" /> </Helmet>

@fricke
Copy link

fricke commented Apr 7, 2019

I have a similar issue and when looking at what is happening there seems to be an issue w/ an array:

on a console.log

tag, primaryAttributeKey =  { innerHTML: [ 'window.__INITIAL_STATE__ = ', ';' ] } innerHTML

So the primaryAttributeKey is innerHTML, which exists, but that value is an array.

I have the following test setup

 <Helmet>
     <script>
         window.__INITIAL_STATE__ = {};
      </script>
  </Helmet>

I'm able to get this working if I use:

<Helmet script={[{
  type: 'text/javascript',
  innerHTML: `window.__INITIAL_STATE__ = Object.assign(window.__INITIAL_STATE__ || {}, ${someState})`

but I have a further problem w/ this that I actually get two rendered script tags, one for when there's no "someState" and one for after there is someState. :/

@tmbtech
Copy link
Contributor

tmbtech commented May 2, 2019

@Way-U-Need What version are you using?

@biker9
Copy link

biker9 commented Aug 8, 2019

It's happened with Helmet 5.2.1 and Webpack 4.39.1 in my case. It not happened with Webpack 3.12

@slorber
Copy link

slorber commented Nov 14, 2019

Also got this issue, using 5.2.1 and the following code, on a Gatsby app:

import React from 'react';
import Helmet from 'react-helmet';
import { AppLocale } from '../appTypes';

// prettier-ignore
const FrontLocaleRedirectionScript = ({ locale }: { locale: AppLocale }) => {
  return (
    <Helmet>
      <script type="text/javascript">
        alert("page locale = " + {locale});
      </script>
    </Helmet>
  );
};

export default FrontLocaleRedirectionScript;

TypeError: tag[primaryAttributeKey].toLowerCase is not a function

  • HelmetUtils.js:121

@febeck
Copy link

febeck commented Dec 12, 2019

On my side I'm running into this issue too. Giving a little bit more context

Currently my team is on a major dependency upgrade and we run into this issue when upgrade the file-loader from v4.3.0 to v5.0.2.

@kembly
Copy link

kembly commented Jan 4, 2020

In case anyone else is still running into this issue...If you use v5 of file-loader, you're going to have to set {options: { esModule: false } } for file-loader in your webpack config.

Due to defaulting to esModule for file-loader in v5, commonJS exports are now being exported as objects with a default property for compatibility with esModules. For HelmetJS, it means that the href and src attributes for links (tag[primaryAttributeKey]) are being exported as { default: '/link-href' } instead of '/link-href'.

For more on the general discussion around compatibility you can check out the thread here webpack/webpack#4742

@pmarxbraun
Copy link

@kembly hi there ! Can't make it work.

Tried adding as stipulated in gatsby-node.js

exports.onCreateWebpackConfig = ({
  stage,
  rules,
  loaders,
  plugins,
  actions,
}) => {
  actions.setWebpackConfig({
    module: {
      rules: [
        {
          use: [
            {
              loader: "file-loader",
              options: {
                esModule: false,
              },
            },
          ],
        },
      ],
    },
  })
}

but throws me this

ERROR 

There was an error compiling the html.js component for the development server.

See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html TypeError: htmlComponentRenderer.default is not a function

  TypeError: htmlComponentRenderer.default is not a function

Any help would be appreaciated. For me it's the AMP Boilerplate code that is causing this.

@benkitzelman
Copy link

benkitzelman commented Sep 22, 2020

I managed to get round it by not using JSX - this code takes an inlined link or script node, and renders it in the head instead of the body:

const childrenAsString = (node) => {
  return (node.children || [])
            .map((ch) => (ch || {}).data)
            .filter(Boolean)
            .join('\n');
};

const HeaderScript = ({ node }) => {
  const innerHTML = node.attribs.src ? null : childrenAsString(node);

  return (
    <Helmet>
      { React.createElement(node.type, { innerHTML, ...node.attribs }, null) }
    </Helmet>
  );
};

@JaffParker
Copy link

Just ran into this error while trying to give 2 strings to a style tag, fixed it by making it one string. It makes sense too, because an array of children doesn't have a function toLowerCase. If you look at the docs, you'll see how they suggest doing it as well:

    {/* inline script elements */}
    <script type="application/ld+json">{`
        {
            "@context": "http://schema.org"
        }
    `}</script>

    {/* noscript elements */}
    <noscript>{`
        <link rel="stylesheet" type="text/css" href="foo.css" />
    `}</noscript>

    {/* inline style elements */}
    <style type="text/css">{`
        body {
            background-color: blue;
        }

        p {
            font-size: 12px;
        }
    `}</style>

Note that each of the style, script and noscript contents is a single string, Helmet only assumes that to be the type of the children

@arslnb
Copy link

arslnb commented Mar 30, 2021

Just ran into this issue with an app bootstrapped with create-react-app 4 with --template typescript. In my case, I solved it by manually pointing to the default export from my file.

<Helmet>
    <link
        rel="icon"
        type="image/png"
        sizes="32x32"
        href={require(file)}
        data-react-helmet="true"
    />
<Helmet/>

Will not work, as @kembly pointed, the import points at {default:'/link'} as opposed to just /link. You can modify the webpack config (in my case with react-rewired or something), or just switch to require(file).default manually, as I did.

@lacdael
Copy link

lacdael commented Apr 19, 2021

I got the error, trying: <script>{ JSON.stringify(data) }</script>

Fix:

  <script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
  />;

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