react-helmet icon indicating copy to clipboard operation
react-helmet copied to clipboard

Body style attribut is not set properly

Open testerez opened this issue 7 years ago • 9 comments

When trying to set <body> style attribute like this:

<Helmet>
  <body style={{background: 'black'}}/>
</Helmet>

It is actually set to <body style="[object Object]"/>

I figured out that I need to pass style attribute as a string to make it work:

<Helmet>
  <body style="background: black"/>
</Helmet>

This is working in the browser but for SSR I get this error:

The style prop expects a mapping from style properties to values, not a string.

Here is how I use helmet for SSR:

const Html = ({children}) => {
  const helmet = Helmet.rewind();
  return (
    <html lang="en" {...helmet.htmlAttributes.toComponent()}>
        <body {...helmet.bodyAttributes.toComponent()}>
          {children}
        </body>
    </html>
  )
}

Am I missing something?

testerez avatar Jan 04 '18 07:01 testerez

I am having the very same problem with react-helmet 5.2.0.

u840903 avatar Feb 13 '18 23:02 u840903

@janjarfalk if it helps, here is the simple workaround I used:

const getBodyStyleAttribute = (
  backgroundUrl?: string,
  backgroundColor?: string,
) => isClient
  ? [
    backgroundUrl && `background-image: url(${backgroundUrl});`,
    backgroundColor && `background-color: ${backgroundColor};`,
  ].filter(s => s).join('')
  : {
    backgroundImage: backgroundUrl ? `url(${backgroundUrl})` : undefined,
    backgroundColor: backgroundColor || undefined,
  };

testerez avatar Feb 14 '18 00:02 testerez

@janjarfalk @testerez I am using a similar solution; though more generic.

import kebabCase from 'lodash/kebabCase';

const getHelmetBodyStyleAttributeValue = (style) => {
  if (typeof window === 'undefined') {
    return style;
  }
  return Object.keys(style).map(key => `${kebabCase(key)}: ${style[key]}`).join(';');
};

It seems to work for everything I have needed so far (though might fail on non standard things as it transforms keys to kebabCase)

AubreyHewes avatar Sep 13 '18 21:09 AubreyHewes

Thanks for sharing @AubreyHewes what about having something similar built into react-helmet?

testerez avatar Sep 13 '18 21:09 testerez

@testerez Good point, I will get a PR going ;-)

AubreyHewes avatar Sep 13 '18 21:09 AubreyHewes

@AubreyHewes @testerez Any update on the PR? Looks stale

matt-whitaker avatar Aug 12 '20 18:08 matt-whitaker

@matt-whitaker I never had any feedback on it.

AubreyHewes avatar Aug 14 '20 18:08 AubreyHewes

@AubreyHewes thats unfortunate. Feels like a bug.

logemann avatar Mar 11 '21 11:03 logemann

I'm using react-helmet with Gatsbyjs. I couldn't understand @testerez and @AubreyHewes examples. I used useEffect to add style attribute to body:

useEffect(() => {
    document.body.setAttribute('style', 'background-color: red;');
}, []);

ghost avatar Nov 14 '21 10:11 ghost