The little icon in the browser tab is just a <link rel="icon"> in the document <head>, and single-page apps sometimes want to change it at runtime — a red dot when there are unread messages, a different logo per workspace, a "recording" indicator. useFavicon does that imperatively: give it a URL and it points the tab's icon there, creating the <link> if the page doesn't already have one.
Implement useFavicon(href). In an effect, find the existing <link rel="icon"> (or create and append one), then set its href to the given URL. Re-run when href changes, and reuse the same element rather than piling up new <link> tags.
function useFavicon(href) {
// side-effect only; returns nothing.
}
function Inbox({ unread }) {
useFavicon(unread ? '/favicon-alert.png' : '/favicon.png');
// tab icon swaps as `unread` flips
}
useFavicon('/logo.png'); // creates <link rel="icon" href="/logo.png"> if absent
head for an existing link[rel~='icon']; only build a new one if none is there.href changes, mutate the same <link>'s href; don't append a fresh link each time or the head fills with duplicates.useEffect, keyed on href.