Skip to content

Instantly share code, notes, and snippets.

@theKashey
Created July 31, 2019 11:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theKashey/caf0549b4d968b405d11afd8e9f2135b to your computer and use it in GitHub Desktop.
Save theKashey/caf0549b4d968b405d11afd8e9f2135b to your computer and use it in GitHub Desktop.
jsLingui compatible "Helmet"
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { createChannel } from 'react-push-channel';
function setDescription(description: string) {
const meta = document.querySelector('meta[name=description]') || document.createElement('meta');
meta.setAttribute('name', 'description');
meta.setAttribute('content', description);
document.head!.appendChild(meta);
}
export const helmet = createChannel<{ title: React.ReactNode; description: React.ReactNode }>({
title: '',
description: '',
});
class Title extends React.PureComponent {
public domNode = document.createElement('div');
public componentDidMount() {
this.componentDidUpdate();
}
public componentDidUpdate() {
document.title = this.domNode.textContent || ':(';
}
public render() {
return ReactDOM.createPortal(this.props.children, this.domNode);
}
}
class Description extends React.PureComponent {
public domNode = document.createElement('div');
public componentDidMount() {
this.componentDidUpdate();
}
public componentDidUpdate() {
setDescription(this.domNode.textContent || ':(');
}
public render() {
return ReactDOM.createPortal(this.props.children, this.domNode);
}
}
export class Helmet extends React.Component {
public state = {
actions: [],
gen: 0,
};
public setHeader = ({ title, description }: any) => {
const { gen } = this.state;
this.setState({
actions: [<Title key={`t${gen}`}>{title}</Title>, <Description key={`d${gen}`}>{description}</Description>],
});
};
public render() {
const { children } = this.props;
const { actions } = this.state;
return (
<React.Fragment>
<helmet.Collector merge={true} callback={this.setHeader}>
{children}
</helmet.Collector>
{actions}
</React.Fragment>
);
}
}
export const PageTitle: React.SFC<{
title: React.ReactNode;
description?: React.ReactNode;
}> = ({ title, description }) => <helmet.Push title={title} description={description} />;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment