fix: (regression 0.57.16) firefox52 not loading frontend #1102
Massimo Melina committed
Oct 18, 2025 at 23:49 UTC
8c0239169f14133b551e4db3138bfec74e057d41
1 file changed
+37
-22
shared/react.ts
+37
-22
@@ -5,7 +5,7 @@ import {
5
useCallback, useEffect, useMemo, useRef, useState
6
} from 'react'
7
import { useIsMounted, useWindowSize, useMediaQuery } from 'usehooks-ts'
8
-import { Callback, domOn, Falsy } from '.'
8
+import { Callback, domOn, Falsy, repeat } from '.'
9
import _ from 'lodash'
10
11
export function useStateMounted<T>(init: T) {
@@ -128,39 +128,54 @@ export function useIsMobile() {
128
129
// workaround for the usability problem caused by sticky headers/footers. Just assign the returned value as ref prop of your sticky element.
130
export function useFixSticky() {
131
- return useOnResize((_w, h, _el, style) => {
131
+ return useOnResize(useCallback((_w, h, _el, style) => {
132
Object.assign(document.documentElement.style, {
133
scrollPaddingTop: `${h + (parseFloat(style.top) || 0)}px`,
134
scrollPaddingBottom: `${h + (parseFloat(style.bottom) || 0)}px`,
135
})
136
- }).refToPass
136
+ }, [])).refToPass
137
}
138
139
// returns props to assign to your component, and a copy of the ref; calls back with [width, height]
140
export function useOnResize(cb: (width: number, height: number, target: HTMLElement, style: CSSStyleDeclaration) => any) {
141
- const observer = useMemo(() =>
142
- new ResizeObserver(_.debounce(([{ contentRect: r, target }]) => {
143
- const style = getComputedStyle(target)
144
- const pw = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
145
- const ph = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
146
- cb(r.width + pw, r.height + ph, target, style)
147
- }, 10)),
148
- [])
149
- const ref = useRef<HTMLElement>()
150
- return {
151
- ref,
152
- refToPass: useCallback((el: any) => {
153
- observer.disconnect()
154
- if (el)
155
- observer.observe(el)
156
- ref.current = el
157
- }, [observer])
158
- }
141
+ const ref = useRef<HTMLElement | null>(null)
142
+ const cleanupRef = useRef(_.noop)
143
+ return useMemo(() => {
144
+ let lastW = -1
145
+ let lastH = -1
146
+
147
+ function measure(el: HTMLElement) {
148
+ const style = getComputedStyle(el)
149
+ const w = (el.clientWidth || el.getBoundingClientRect().width)
150
+ + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
151
+ + parseFloat(style.borderRightWidth) - parseFloat(style.borderLeftWidth)
152
+ const h = (el.clientHeight || el.getBoundingClientRect().height)
153
+ + parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
154
+ + parseFloat(style.borderBottomWidth) - parseFloat(style.borderTopWidth)
155
+ if (w !== lastW || h !== lastH)
156
+ cb(lastW = w, lastH = h, el, style)
157
+ }
158
+
159
+ return {
160
+ ref,
161
+ refToPass(el: HTMLElement | null) {
162
+ ref.current = el
163
+ cleanupRef.current()
164
+ cleanupRef.current = _.noop
165
+ if (!el) return
166
+ if (!window.ResizeObserver)
167
+ return cleanupRef.current = repeat(500, () => measure(el))
168
+ const ro = new ResizeObserver(_.debounce(entries => measure(entries[0].target), 10))
169
+ ro.observe(el)
170
+ cleanupRef.current = () => ro.disconnect()
171
+ }
172
+ }
173
+ }, [cb])
174
}
175
176
export function useGetSize() {
177
const [size, setSize] = useState<[number,number]>()
163
- const { refToPass, ref } = useOnResize((w, h) => setSize([w, h]))
178
+ const { refToPass, ref } = useOnResize(useCallback((w, h) => setSize([w, h]), []))
179
return useMemo(() => ({
180
w: size?.[0],
181
h: size?.[1],