Skip to content

Commit 0a4901f

Browse files
committed
fix(favicon): record an icon that failed before hydration
onError never fires for a failure React missed, so the fallback never showed and any remount asked for the icon again: 204 answers are not reusable within a document, which is what Links' first paint shows as every favicon read twice. The ref now records the failure at hydration; decode separates a broken image from an SVG with no intrinsic size.
1 parent 56ae7e2 commit 0a4901f

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

‎apps/sim/components/favicon.tsx‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,25 @@ interface FaviconProps {
3232
export function Favicon({ host, fallback, className, onLoad }: FaviconProps) {
3333
const [, rerender] = useReducer((failures: number) => failures + 1, 0)
3434
if (!host || knownMisses.has(host)) return fallback
35+
const recordMiss = () => {
36+
knownMisses.set(host, true)
37+
rerender()
38+
}
3539
return (
3640
<img
3741
ref={(image) => {
38-
if (onLoad && image?.complete && image.naturalWidth > 0) onLoad()
42+
if (!image?.complete) return
43+
if (image.naturalWidth > 0) onLoad?.()
44+
// A failure before hydration fires no onError, and a remount would ask for the icon again.
45+
else void image.decode().catch(recordMiss)
3946
}}
4047
src={faviconSrc(host)}
4148
alt=''
4249
loading='lazy'
4350
decoding='async'
4451
className={cn('rounded-sm', className)}
4552
onLoad={onLoad}
46-
onError={() => {
47-
knownMisses.set(host, true)
48-
rerender()
49-
}}
53+
onError={recordMiss}
5054
/>
5155
)
5256
}

0 commit comments

Comments
 (0)