react-helmet
react-helmet copied to clipboard
Order of stylesheets changing
I'm passing two dynamic links to stylesheets to react-helmet
like this:
const links = [
{
rel: "stylesheet",
href: `/dist/stylesheets/themes/${someVariable}.css`
},
{
rel: "stylesheet",
href: "/dist/stylesheets/core.css"
}
];
<Helmet links={links} />
On first and subsequent renders everything is correct:
<link rel="stylesheet" href="/dist/stylesheets/themes/dark.css" data-react-helmet="true">
<link rel="stylesheet" href="/dist/stylesheets/core.css" data-react-helmet="true">
However as soon as someVariable
changes, and the head tags are recomputed, the order changes to this:
<link rel="stylesheet" href="/dist/stylesheets/core.css" data-react-helmet="true">
<link rel="stylesheet" href="/dist/stylesheets/themes/light.css" data-react-helmet="true">
Throwing the whole design away. Is there a way to enforce the order of link tags?
@Anahkiasen Thanks for your interest in Helmet. You can set the order of the tags in your Helmet, but because of some checks we do for FOUC, the order will change as you've noticed. The checks we have in place make sure that only the required DOM changes are made and nothing more. So, in your case core.css
will remain untouched, while the new light.css
is added to the end of the document head.
We can look into the possibility of maintaining the order of the tags, but in the meantime, could you write the css in a way that let's the second file swap out to change the theme?
You can trick Helmet into thinking that the DOM has changed when it actually hasn't but adding a querystring that updates when you update someVariable
. This way both link
tags will be re-rendered.
{
rel: "stylesheet",
href: `/dist/stylesheets/core.css?theme=${someVariable}`
}
<Helmet - links={links} + link={links} />
props link
work, links
does not!.
I have tried the following approach and the order is maintained (using typescript here)
import { Helmet } from "react-helmet"
/**
* Used to dynamically add custom client specific css
*/
export const buildClientCssHelmet = (baseUrl: string, resourceBasePath: string, clientCss?: Array<string>, commonResourceBasePath?: string, commonCss?: Array<string>) => {
const mapCommonStyles = buildStyleMap(baseUrl, commonResourceBasePath, commonCss)
const mapClientStyles = buildStyleMap(baseUrl, resourceBasePath, clientCss)
/*NOTE: going with the idea of making changes in client specific css which should override the common css, here in the array the last element will have highest priority */
const mergeStyles = [...mapCommonStyles, ...mapClientStyles]
return <Helmet link={mergeStyles} />
}
const buildStyleMap = (baseUrl:string, path?:string, css ?: Array<string>) =>{
if(css==undefined || path==undefined) return []
return css.map(item => {
return {
rel: "stylesheet",
type: "text/css",
href: baseUrl.concat(path, item)
}
})
}
Usage:
Inside react component
{buildClientCssHelmet("http://localhost:3000", "/client1", ["client1.css"], "/common", ["common.css"])}