tizmagik / react-head Goto Github PK
View Code? Open in Web Editor NEW⛑ SSR-ready Document Head tag management for React 16+
License: MIT License
⛑ SSR-ready Document Head tag management for React 16+
License: MIT License
We get a JS exception when using the package in IE11 in this line (index.esm.js):
According to this page , the remove() method is not supported at all in IE.
We currently use the polyfill mentioned in the same link as a workaround, but it would be much better if the package already handles that.
As per discussion in #18, creating an issue that can serve as starting point for some documentation around using react-head
with SSR streaming. Both #14 and #18 mention that there is support for it, just no recommended usage.
For reference, here are the docs that react-helmet-async
has for streaming SSR:
https://github.com/staylor/react-helmet-async#streams
cc: @jamesjjk
I was hoping to create a base tag, and found it is missing. It should be added, but more generally the generic HeadTag should be exposed in the exports.
Canonical link is duplicated, in my case I found it it repeated 3 times
First off, love the lib. Would there be some merit to cascading a <link rel="canonical" ... />
tag? (link tags aren't cascaded and for good reason)
But this particular link
tag has a uniqueness requirement akin to title
and other meta
tags,
Multiple canonicals
are ignored (this is old, but looks to be still relevant)
Specify no more than one rel=canonical for a page. When more than one is specified, all rel=canonicals will be ignored.
To bring this to a question: right now canonical
is required to be set on every page, but should this be handled as an edge case and cascaded, or maybe there something a little more interesting here where we can leverage the platform and give any link
tag the ability to cascade given a unique identifier via an id
or class
(or other) attribute?
One last thing, the canonical
tag in the readme is using a content
attribute but I think you want an href
attribute: <Link rel="canonical" content="http://jeremygayed.com/" />
to <Link rel="canonical" href="http://jeremygayed.com/" />
Thank you for you time
There's some test case descriptions already written out and checked in, but they need the actual tests written
Version: v3.0.0
Error stack:
index.esm.js?d732:58 Uncaught DOMException: Failed to execute 'querySelector' on 'Element': 'meta[property="og:title"][content=""Có tâm" như Lý Quý Khánh chụp ảnh cho Hà Hồ: Lần nào cũng hết hồn chim én!"][data-rh=""]' is not a valid selector.
at HeadTag.componentDidMount (webpack-internal:///./node_modules/react-head/dist/index.esm.js:74:33)
at commitLifeCycles (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:14361:22)
at commitAllLifeCycles (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:15462:7)
at HTMLUnknownElement.callCallback (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:100:14)
at Object.invokeGuardedCallbackDev (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:138:16)
at invokeGuardedCallback (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:187:29)
at commitRoot (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:15603:7)
at completeRoot (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:16618:34)
at performWorkOnRoot (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:16563:9)
at performWork (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:16482:7)
Quite serious that page just gone white.
It seems cause of meta content which include double quote mark(")
Maybe do not use content as part of querySelector? (or perform suitable escaping before query)
And, I only want head tags performs on server, and leave it alone at client side (My MPA do not use front-ending routing), Maybe add some option to do this.
Add a new route to the example app that changes the <title />
tag to show how this library works with client-side Single Page Apps.
I'm using client-side rendering and react-head
is not able to replace a default tag that I provided on my HTML template. It only adds a new <title>
tag at the end of the head, and due to the browser behavior, only the first one is actually used. react-helmet
as a reference supported this fine.
template.html
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="react-mount"></div>
</body>
</html>
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Title, HeadProvider } from 'react-head';
ReactDOM.render(
<div>
<HeadProvider>
<Title>Test2</Title>
</HeadProvider>
</div>
document.getElementById('react-mount'),
)
The expected behavior for me is that Test2
is going to replace and be the title of the page, but what happens is that Test
remains as the title, as its tag is positioned first.
Figure out why React 16 shows this warning:
Warning: Expected server HTML to contain a matching <title> in <div>.
You can see this in action with the example app:
npm run build
cd example
npm install
npm start
Then navigate to http://localhost:3000
Currently, react-head utilizes data-rh
attributes in order to manage the tags that it creates. By default, react-head avoids touching tags that it doesn't know about (that don't have data-rh
attributes). This is so that static tags that are part of a static HTML template are not touched.
There's been a few issues (both in this project and react-helmet) from folks who are interested in:
While these two items are certainly separate, they are closely related and we might be able to kill two birds with one stone depending on our approach.
One solution, as proposed in #84 is to define an explicit whitelist prop:
/* on server */
const headTags = [];
<HeadProvider headTags={headTags} whitelist={['title', '[name="description"]', '[property^="og:"]'}>
<App />
</HeadProvider>
/* on client */
<HeadProvider whitelist={['title', '[name="description"]', '[property^="og:"]'}>
<div id="app">
<Title>Title of page</Title>
// ...
</div>
</HeadProvider>
This solution has the following benefits:
While this works, it has the following drawbacks:
[foo^=bar]
)The implementation can be explored in the WIP PR by @CanRau
Expanding on Option 1, we could auto-generate the necessary "selector set" as you go (opt-in to this behavior with autoWhitelist
prop on HeadProvider
):
/* server */
const headTags = [];
<HeadProvider headTags={headTags} autoWhitelist>
<App>
// ... within any component, head tags are rendered as normal
<Meta name="blah-long-name" content="lots of content here" />
<Title>Title of page</Title>
</App>
</HeadProvider>
/* on client */
<HeadProvider>
<App />
</HeadProvider>
Note that
autoWhitelist
prop isn't very expressive/meaningful without context. Maybe we can come up with a better name?raw
?clean
? Any other ideas?
On the server, as we render head tags, if any of them include a whitelist
prop, we build up the selector set necessary to identify which tags were inserted by react-head (basically the selector set that was manually created in Option 1 above). We return this as a renderable DOM element as part of the headTags[]
array with some unique ID that we grab from the DOM and provide as context during client rendering:
const headTags = [
// normal head tags
'<meta name="blah" content="foo" />',
'<title>Title of page</title>',
// new: the generated whitelist selector set, to be injected during SSR
// we'd basically JSON.parse() this content on the client and use
// as part of the querySelectorAll:
`<script id="react-head-whitelist" type="text/template">
[
'meta[name="blah-long-name"][content="lots of content here"]',
'title'
]
</script>
`
]
CONs:
meta[name^="blah"][content^="lots"]
PROs:
title
, instead of also including the full text content). Alternatively we could force opt-in to mangling by requiring an additional specific prop, <title mangle>Title of page</title>
but not crazy about that idea.As a tweak to Option 2, we could individually require opt-in, if we wanted to support whitelisting only individual elements, we could support an explicit whitelist
prop on each head tag instead of an autoWhitelist
prop on the HeadProvider
.
<title whitelist>Title of Page</title>
In this scenario you'd have a mix of data-rh
and #react-head-whitelist
selectors.
Not sure how popular this option would be and it complicates the implementation slightly so I'd almost rather have it be all or nothing. Thoughts?
PRO:
CON:
The above assume that folks don't want react-head to manage tags that it hasn't explicitly rendered. There is a "nuclear" option of allowing folks to opt-in to having react-head mangle all tags:
/* server */
const headTags = [];
<HeadProvider headTags={headTags} manageAllTags>
<App>
// ... within any component, head tags are rendered as normal
<Meta name="blah-long-name" content="lots of content here" />
<Title>Title of page</Title>
</App>
</HeadProvider>
/* on client */
<HeadProvider manageAllTags>
<App />
</HeadProvider>
If manageAllTags
is set, we can avoid rendering data-rh
attributes and just have a very greedy selector on the client, something like: head > title, head > meta
... which would select all tags in <head />
whether or not they were created by react-head. This would work but would require that users express all their tags in the React tree and not just rely on static HTML templates. This is okay if we make this opt-in and explain thoroughly in the documentation.
PROs:
CONs:
If I follow the instructions in CONTRIBUTING.md
, I am unable to get the dev server to run, with any amount of prodding.
OSX 10.13.4, Node 10.10.0, nvm or system/Brew didn't seem to matter.
Playing around with config to try to get it to run or checking out an earlier version will sometimes provide ES module / Babel looking errors but checkout out current master
and following the instructions provides:
npm ERR! prepareGitDep 1>
npm ERR! prepareGitDep > [email protected] prepare /Users/jay/proj/ass/react-head
npm ERR! prepareGitDep > npm run test && npm run build
npm ERR! prepareGitDep
npm ERR! prepareGitDep
npm ERR! prepareGitDep > [email protected] test /Users/jay/proj/ass/react-head
npm ERR! prepareGitDep > jest --no-cache
npm ERR! prepareGitDep
npm ERR! prepareGitDep
npm ERR! prepareGitDep 2> npm WARN install Usage of the `--dev` option is deprecated. Use `--only=dev` instead.
npm ERR! prepareGitDep FAIL tests/ssr.test.js
npm ERR! prepareGitDep ● fails if headTags is not passed to <HeadProvider />
npm ERR! prepareGitDep
npm ERR! prepareGitDep expect(function).toThrowError(regexp)
npm ERR! prepareGitDep
npm ERR! prepareGitDep Expected the function to throw an error matching:
npm ERR! prepareGitDep /headTags array should be passed/
npm ERR! prepareGitDep Instead, it threw:
npm ERR! prepareGitDep ReferenceError: invariant is not defined
npm ERR! prepareGitDep 69 |
npm ERR! prepareGitDep 70 | render() {
npm ERR! prepareGitDep > 71 | invariant(
npm ERR! prepareGitDep | ^
npm ERR! prepareGitDep 72 | typeof window !== 'undefined' || Array.isArray(this.props.headTags),
npm ERR! prepareGitDep 73 | 'headTags array should be passed to <HeadProvider /> in node'
npm ERR! prepareGitDep 74 | );
npm ERR! prepareGitDep
npm ERR! prepareGitDep at HeadProvider.render (src/HeadProvider.js:71:5)
npm ERR! prepareGitDep at d (node_modules/react-dom/cjs/react-dom-server.node.production.min.js:28:211)
npm ERR! prepareGitDep at wa (node_modules/react-dom/cjs/react-dom-server.node.production.min.js:28:493)
npm ERR! prepareGitDep at a.render (node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:48)
npm ERR! prepareGitDep at a.read (node_modules/react-dom/cjs/react-dom-server.node.production.min.js:32:288)
npm ERR! prepareGitDep at renderToStaticMarkup (node_modules/react-dom/cjs/react-dom-server.node.production.min.js:43:75)
npm ERR! prepareGitDep at tests/ssr.test.js:76:5
npm ERR! prepareGitDep at Object.<anonymous> (node_modules/expect/build/to_throw_matchers.js:51:9)
npm ERR! prepareGitDep at Object.throwingMatcher [as toThrowError] (node_modules/expect/build/index.js:320:33)
npm ERR! prepareGitDep at Object.toThrowError (tests/ssr.test.js:81:6)
npm ERR! prepareGitDep at Object.toThrowError (tests/ssr.test.js:81:6)
npm ERR! prepareGitDep
npm ERR! prepareGitDep ● fails if headTags is not an array
npm ERR! prepareGitDep
npm ERR! prepareGitDep expect(function).toThrowError(regexp)
npm ERR! prepareGitDep
npm ERR! prepareGitDep Expected the function to throw an error matching:
If I render a Title head tag in my root component and then another with a different value in a child component it results in two title tags being collected on the server. Are we meant to filter collected tags manually so that there are no duplicates?
Getting this TS error
Type '{ children: Element; }' has no properties in common with type 'IntrinsicAttributes & { headTags?: ReactElement<unknown, string | JSXElementConstructor>[] | undefined; }'.
Fix for this-
since HeadProvider uses children
prop, it's typescript definition should include children: ReactNode
In the readme renderString is used to render the headTags array. This adds a data-reactroot attribute to every element. Since only data-rh is used to "hydrate" anyway, renderToStaticMarkup might be a better choice to save a few bytes and get cleaner markup.
I'm adding an option to remove [data-reactroot=""] from the queryselector string so your library supports both static stream and static markup. Like the simplicity of what you have done!
Can react-head be updated when i am on the some component and that component get more data after certain scroll (lazy load) to render then can i update the meta with total count of product?
I following the example to try to run this library on dev env and and prod env with ssr.
dev env is working fine but prod env with ssr is crashing with:
(node:25652) UnhandledPromiseRejectionWarning: Error: Invariant failed
at index (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/build/Routes.js:12781:11)
at Object.children (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/build/Routes.js:2365:110)
at a.render (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:400)
at a.read (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:34:288)
at Object.renderToString (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:45:6)
at loadBranchData.then._data (/home/pc/Documents/funspace/babysearch/isomorphic-react-redux-saga-ssr/lib/server/ssr.js:116:36)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
(node:25652) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
I took a screenshot to show you what the line /isomorphic-react-redux-saga-ssr/build/Routes.js:2365
correspond to:
My SSR setup is pretty straightforward with:
loadBranchData(location, routes).then(_data => {
const context = {
splitPoints: [],
};
const headTags = [];
const rootComponent = PROD ? (
<IntlProvider locale={locale} messages={messages[locale]}>
<Provider store={store}>
<HeadProvider headTags={headTags}>
<StaticRouter location={location} context={context}>
<Layout />
</StaticRouter>
</HeadProvider>
</Provider>
</IntlProvider>
) : null;
const markup = ReactDOMServer.renderToString(rootComponent);
const state = store.getState();
const html = ReactDOMServer.renderToStaticMarkup(
<Html
PROD={PROD}
assets={assets}
markup={markup}
state={state}
splitPoints={context.splitPoints}
localeData={localeData[locale]}
/>
);
res.send(doctype + html);
it is crashing on the line const markup = ReactDOMServer.renderToString(rootComponent);
My client is having this code:
const rootEl = document.getElementById("root");
const renderApp = localeData => {
hydrate(
<IntlProvider locale={appLocale} messages={localeData}>
<Provider store={store}>
<HeadProvider>
<AppContainer history={history} />
</HeadProvider>
</Provider>
</IntlProvider>,
rootEl
);
};
and down the AppContainer component and many other child components I render some Title and Meta
const DirectoryLayout = _props => (
<div>
<Title>Browse Directory</Title>
<Meta name="description" content="Some directory" />
<Meta property="og:title" content="Directory" />
<Meta property="og:image" content="path/to/image.jpg" />
<AlphabetLinks />
<AlphabetDirectory />
</div>
);
Can you please help solving this issue?
Thanks for providing such a great package! Was running into react-helmet’s deprecated lifecycle API and was happy to find this solution.
I’m using it in a TypeScript environment, which (obviously) doesn’t seem to understand Flow, and needs definitions. The @types repo recommends shipping these TS definitions in the original package rather than in a separate @types/react-head
repo (workaround for when the original package is missing definitions).
Would it be possible to ship the following definition file as dist/index.d.ts
to npm? I’m using the following locally and this seems to make TypeScript happy. Happy to submit a PR if that’s helpful. Feedback welcome.
declare module 'react-head' {
export const HeadProvider: React.ComponentClass<{
headTags?: React.ReactChildren;
}>;
export const Link: React.FunctionComponent<React.HTMLProps<HTMLLinkElement>>;
export const Meta: React.FunctionComponent<React.HTMLProps<HTMLMetaElement>>;
export const Style: React.FunctionComponent<React.HTMLProps<HTMLStyleElement>>;
export const Title: React.FunctionComponent<React.HTMLProps<HTMLTitleElement>>;
}
TLDR: <Meta />
appears to not have support for the itemprop
prop, which can be a great tool for improving SEO.
Problem: <Meta />
tags that have an itemProp
set don't get added to the DOM.
Ask: Can you add support for the itemprop
attribute on <Meta />
? Alternatively, would you accept a PR if I did?
More context:
<meta />
supports the itemprop
attribute, which is a way of annotating markup so that Google can know what a specific element corresponds to. Typically, you use it on the element it the text directly pertains to -- so you'd have itemProp="datePublished"
on the date published timestamp.
Sometimes, you can't. Not all metadata is displayed in the page. In that case, you can provide a <meta itemprop="microdata_attribute_name" content="microdata_attribute_value" />
tag which lets you invisibly add the meta tag, so that Google still knows about the metadata even though it's not actually visible to the user in the same format.
Hi,
I can't have SSR in my current project as my backend is developed by someone else in PHP,
all I have is a server serving static Build of my App built over create-react-app.
It's a blog basically with all normal functionality like reading, creating of blog post and sharing the same
my issue is SEO I am unable to preview the dynamic headers and meta data on social site like facebook and other
please help.
I implemented react-head in a small project, and got it working, great!
I did have some trouble however before I got it working, and had to make some modifications, I wonder if this may help others.
Because my server setup is somewhat different, I wanted to render the complete html using a react template that includes the complete head element. But I found that the HeadTag component only works correctly when the collected elements are rendered using renderToString(headTags)
, as shown in the docs/sample. HeadTag selects elements for client-side replacement by querying with [data-reactroot=""]
, which is added only to root elements by the renderToString function.
Doing it any other way breaks it. Rendering the headTags using a plain <head>{headTags}</head>
does not insert the data-reactroot=""
attribute, causing duplicate elements. Using <head>{renderToString(headTags)}</head>
escapes it. Removing the [data-reactroot=""]
selector breaks the clientside. In the end, I solved it by adding a specific data-ssr=""
attribute on the server component and selecting on that. This makes HeadTag independent from the way it is rendered on the server. I also added a key to the client-side version, to get rid of some React warnings.
The result is this (it's also in typescript):
interface HeadTagProps {
tag?: string;
}
export default class HeadTag extends React.Component<HeadTagProps & (React.MetaHTMLAttributes<{}> | React.LinkHTMLAttributes<{}>)> {
static contextTypes = {
reactHeadTags: PropTypes.object,
};
static propTypes = {
tag: PropTypes.string,
};
static defaultProps = {
tag: 'meta',
};
state = {
canUseDOM: false,
};
componentDidMount() {
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({ canUseDOM: true });
const { tag, children, ...rest } = this.props; // eslint-disable-line react/prop-types
const ssrTags = document.head.querySelector(`${tag}${buildSelector(rest)}[data-ssr=""]`);
/* istanbul ignore else */
if (ssrTags) {
ssrTags.remove();
}
}
render() {
const { tag: Tag, ...rest } = this.props;
if (this.state.canUseDOM) {
const Comp = <Tag key={`${Tag}${Object.keys(rest).filter(key => key !== "content" && key !== "children").map(key => ':' + key).join('')}`} {...rest} />;
return ReactDOM.createPortal(Comp, document.head);
}
// on client we don't require HeadCollector
if (this.context.reactHeadTags) {
const ServerComp = <Tag data-ssr="" {...rest} />;
this.context.reactHeadTags.add(ServerComp);
}
return null;
}
}
It's only three small changes, but server rendering is much more flexible, now I can render like this:
....
const GlobalScript = ({ state }) => <script dangerouslySetInnerHTML={{ __html: "window.initialReduxState = " + JSON.stringify(state) }} />
const Html = ({ headTags, appString, state }) => (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/dist/site.css" />
<base href="/" />
{headTags}
</head>
<body>
<div id="react-app" dangerouslySetInnerHTML={{__html: appString}} />
<GlobalScript state={state} />
<script src="/dist/vendor.js"></script>
<script src="/dist/main-client.js"></script>
</body>
</html>
);
// Once any async tasks are done, we can perform the final render
// We also send the redux store state, so the client can continue execution where the server left off
params.domainTasks.then(() => {
let headTags: React.ReactElement<any>[] = [];
const appString = renderToString(<App headTags={headTags} />);
resolve({
html: renderToStaticMarkup(<Html headTags={headTags} appString={appString} state={store.getState()} />)
});
}, reject); // Also propagate any errors back into the host application
We have a couple of breaking changes and I need some brainstorming before the next release.
HeadProvider
has necessary headTags
prop which is not necessary for client-only apps so users should specify it as empty arraysHeadProvider
is used to solve cascading tagsHeadTag
is able to work without HeadProvider
; will always render tagtag
prop in HeadTag
Questions
headTags
with empty array?HeadProvider
in the tree by throwing an error if context value is null
?componentDidUpdate
if tag
prop is changed or just remove HeadTag
from public api and provide more aliases?/cc @tizmagik
Currently renderToString
of headTags
with parent elements gives Warning: Each child in an array or iterator should have a unique "key" prop.
.
const headHtml = renderToString(
<head>
{sheet.getStyleElement()}
{headTags}
</head>
)
So as a workaround I'm using React.createElement
+ React.Fragment
.
const headHtml = renderToString(
<head>
{sheet.getStyleElement()}
{React.createElement(React.Fragment, {}, ...headTags)}
</head>
)
It would be good if react-head
had it's own utility to handle this situation, e.g:
export const headTagsToElement = headTags =>
React.createElement(React.Fragment, {}, ...headTags);
I would glad to add PR after merge of #69.
Hi,
Do you have plan for renderToNodeStream support?
Thanks
I noticed that there is no support for script tags. This is useful for e.g. conditionally including trackers in SSR.
React-helmet can do it, but unfortunately it loads the script twice on SSR if you also render it on the client.
Would be nice to create some aliases for convenience, so that instead of doing this:
import HeadTag from 'react-head';
<HeadTag tag="link" rel="canonical" content="http://jeremygayed.com/" />
You could do this:
import { Link } from 'react-head'; // maybe HeadLink better?
<Link rel="canonical" content="http://jeremygayed.com/" />
The common aliases should be:
Title
Style
Meta
Link
Technically base
and script
are also allowed, but I can't think of a use case where you don't already know those values server-side.
A potentially useful feature is the ability to support cascading tags with the same tag
and/or name
attribute.
This may be just a matter of collecting tags to an associative array (object) where the key is the tag name and then overriding previously collected tags as the components render in order.
Similar functionality exists in react-helmet which is inspiration for this library to begin with
I could imagine that this library is mostly complete and so it doesn't need further work, but do new features like React Server components need any special consideration? It's hard to tell.
Hi, just stumbled upon your module, while trying to evaluate the use of React Portals for and as your plugin proofs it does indeed 👍
haven't had the time to test it out yet, but I was actually looking for an alternative to react-helmet because this nfl/react-helmet#79 kind of bugs me..
not sure how big of an impact this has, but wanted to try it out and didn't liked the idea of hacking the attribute away like mentioned in the comments..
any thoughts on this?
by the way, in my case I'm using GatsbyJs
Wonderful package :) I've been using it for a year or so, and it's awesome.
Question on usage when rendering a computed attribute that contains an ampersand (&
). React likes to escape that to &
... any suggested workarounds?
This is the use case:
<Meta
property="og:image"
content={imageUrl + '?height=630&width=1200'}
/>
The content
attribute ends up looking like this when rendered with ReactDOM.renderToStaticMarkup
:
content="https://example.com/image.jpg?height=630&width=1200"
Thanks!
Hey you should consider also escaping selector strings:
/* eslint no-useless-escape:0 */
const buildSelector = obj =>
Object.keys(obj)
.map(k => {
const cnt = obj[k].replace(/["\\]/g, '\\$&');
return `[${k}="${cnt}"]`;
})
.join('');
export default buildSelector;
While trying to migrate to react-head I noticed react-helmets and I'm not sure if current react-head can do this already?
If yes I would like some help, if not might this be integrated some day or should I handle it differently?
By the way, the lang attribute is still relevant as far as I can tell right?
edit: should have mentioned that I have actually multiple languages, so it's not about a static declaration but about a dynamic one based on props
maybe I just update it using plain js?
When trying to add the following Meta tags (3.0.0-1):
<Title>{title}</Title>
<Meta name="description" content="The title" />
<Meta property="og:description" content="Some description" />
<Meta property="og:image" content="http://example.com/image.jpg" />
<Meta property="og:title" content="OG title" />
<Meta property="og:sometag" content="someValue" />
Only the first and last one is actually collected and rendered.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.