You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I spent some time today coming up with a design that is closer to Helmet. It's a naive implementation, but it works well and can provide more flexibility than solid-meta's current design.
HeadProvider.tsx:
import_from"lodash-es";import{Component,createContext,createRenderEffect,ParentComponent,useContext}from"solid-js";typeTitleFormatter=(text: string|null)=>string|null;exportinterfaceHeadContextType{setMeta: (name: string,content: string)=>void;setTitle: (text: string|null)=>void;setTitleFormatter: (formatter: TitleFormatter)=>void;}constHeadContext=createContext<HeadContextType>();constHeadProvider: ParentComponent=props=>{lettitleFormatter: TitleFormatter=(text: string|null)=>text;constvalue: HeadContextType={setMeta(name,content){constmetaElements: NodeListOf<HTMLMetaElement>=document.head.querySelectorAll(`meta[name='${name}']`);if(metaElements.length>0){for(constmetaElementofmetaElements){metaElement.content=content;}}else{constmetaElement=document.createElement("meta");metaElement.name=name;metaElement.content=content;document.head.appendChild(metaElement);}},setTitle(text){consttitleElements=document.head.getElementsByTagName("title");if(titleElements.length>0){for(consttitleElementoftitleElements){titleElement.textContent=titleFormatter(text);}}else{consttitleElement=document.createElement("title");titleElement.textContent=titleFormatter(text);document.head.appendChild(titleElement);}},setTitleFormatter(formatter){titleFormatter=formatter;}};return<HeadContext.Providervalue={value}>{props.children}</HeadContext.Provider>;};export{HeadProvider};exportinterfaceTitleProps{formatter?: TitleFormatter;text?: string|null;}exportconstTitle: Component<TitleProps>=props=>{constcontext=useContext(HeadContext);if(_.isNil(context)){thrownewError("Must use within a HeadContext");}createRenderEffect(()=>{if(!_.isNil(props.formatter)){context.setTitleFormatter(props.formatter);}if(!_.isUndefined(props.text)){context.setTitle(props.text);}});returnnull;};exportinterfaceMetaProps{name: string;content: string;}exportconstMeta: Component<MetaProps>=props=>{constcontext=useContext(HeadContext);if(_.isNil(context)){thrownewError("Must use within a HeadContext");}createRenderEffect(()=>{context.setMeta(props.name,props.content);});returnnull;};
Example usage:
<HeadProvider><Titleformatter={text=>`${text} - My Site`}/><Titletext="My Page"/><Metaname="og:title"content="The Title"/></HeadProvider>
The <Title> component looks for a <title> elements inside <head> and then overwrites their textContent with the value of the text prop. It also allows the developer to provide a formatter function that is passed the desired text--say, a specific page's title--and, in my example, append the website name to the end of it. The code sets the <title> element's textContent property to My Page - My Site. I'm wondering if it would be better to change document.title directly, but I'm not sure of the pros and cons.
The <Meta> component is similar in that it looks for matching elements inside <head> and, if they exist, overwrites their content properties. If they don't exist, a new <meta> element is created.
The design of each head tag component could be improved to allow for all props similar to your existing code. I didn't do that for the sake of brevity.
I don't have any performance-related code in my example (e.g., no refs). I'm also not sure if my reactivity code is correct (I tried to write code similar to your current implementation). I am still very new to SolidJS.
The text was updated successfully, but these errors were encountered:
I spent some time today coming up with a design that is closer to Helmet. It's a naive implementation, but it works well and can provide more flexibility than
solid-meta
's current design.HeadProvider.tsx
:Example usage:
The
<Title>
component looks for a<title>
elements inside<head>
and then overwrites theirtextContent
with the value of thetext
prop. It also allows the developer to provide a formatter function that is passed the desired text--say, a specific page's title--and, in my example, append the website name to the end of it. The code sets the<title>
element'stextContent
property toMy Page - My Site
. I'm wondering if it would be better to changedocument.title
directly, but I'm not sure of the pros and cons.The
<Meta>
component is similar in that it looks for matching elements inside<head>
and, if they exist, overwrites theircontent
properties. If they don't exist, a new<meta>
element is created.The design of each head tag component could be improved to allow for all props similar to your existing code. I didn't do that for the sake of brevity.
I don't have any performance-related code in my example (e.g., no refs). I'm also not sure if my reactivity code is correct (I tried to write code similar to your current implementation). I am still very new to SolidJS.
The text was updated successfully, but these errors were encountered: