@shopify/react-html
Version:
A component to render your react app with no static HTML.
95 lines (79 loc) • 2.38 kB
text/typescript
import {useEffect, useContext} from 'react';
import {useServerEffect} from '@shopify/react-effect';
import {FirstArgument} from '@shopify/useful-types';
import {HtmlContext} from './context';
import {HtmlManager} from './manager';
export function useDomEffect(
perform: (manager: HtmlManager) => () => void,
inputs: unknown[] = [],
) {
const manager = useContext(HtmlContext);
const effect = () => {
perform(manager);
};
useServerEffect(effect, manager.effect);
useEffect(effect, [manager, ...inputs]);
}
export function useTitle(title: string) {
useDomEffect(manager => manager.addTitle(title), [title]);
}
export function useLink(link: React.HTMLProps<HTMLLinkElement>) {
useDomEffect(manager => manager.addLink(link), [JSON.stringify(link)]);
}
export function useMeta(meta: React.HTMLProps<HTMLMetaElement>) {
useDomEffect(manager => manager.addMeta(meta), [JSON.stringify(meta)]);
}
export function usePreconnect(source: string) {
useDomEffect(
manager =>
manager.addLink({
rel: 'preconnect',
href: source,
}),
[source],
);
}
export function useFavicon(source: string) {
useDomEffect(
manager =>
manager.addLink({
rel: 'shortcut icon',
type: 'image/x-icon',
href: source,
}),
[source],
);
}
export function useLocale(locale: string) {
useDomEffect(manager => manager.addHtmlAttributes({lang: locale}), [locale]);
}
export function useHtmlAttributes(
htmlAttributes: FirstArgument<HtmlManager['addHtmlAttributes']>,
) {
useDomEffect(manager => manager.addHtmlAttributes(htmlAttributes), [
JSON.stringify(htmlAttributes),
]);
}
export function useBodyAttributes(
bodyAttributes: FirstArgument<HtmlManager['addBodyAttributes']>,
) {
useDomEffect(manager => manager.addBodyAttributes(bodyAttributes), [
JSON.stringify(bodyAttributes),
]);
}
export function useClientDomEffect(
perform: (manager: HtmlManager) => () => void,
inputs: unknown[] = [],
) {
const manager = useContext(HtmlContext);
useEffect(() => {
perform(manager);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [manager, perform, ...inputs]);
}
export function useServerDomEffect(
perform: (manager: HtmlManager) => () => void,
) {
const manager = useContext(HtmlContext);
useServerEffect(() => perform(manager), manager.effect);
}