PoppingPopper
PoppingPopper10mo ago

poppingpopper – 19-07 Oct 18

Hey! I'm trying to build a somewhat responsive page and I'm using a resize observer to get the width of the parent element to determine the width of my charts. For some reason the width changes in increments instead of immediately after the debounce interval I've set. Can you help me figure out why this is happening and how I might fix it? (Also open to constructive criticism about the way I'm approaching it as well)
Solution:
Message Not Public
Sign In & Join Server To View
Jump to solution
19 Replies
PoppingPopper
PoppingPopper10mo ago
Here is the resize observer hook:
import { useEffect, useState } from 'react'
import { useDebouncedCallback } from 'use-debounce'

interface Dimensions {
width: number
height: number
}

export function useDebouncedResizeObserver(element: HTMLElement | null, delay: number): Dimensions {
const [dimensions, setDimensions] = useState<Dimensions>({ width: 0, height: 0 })
const delayedSetDimensions = useDebouncedCallback(setDimensions, delay)

useEffect(() => {
if (!element) return

const resizeObserver = new ResizeObserver((entries) => {
const { width, height } = entries[0].contentRect
delayedSetDimensions(() => ({ width, height }))
})

resizeObserver.observe(element)

// Cleanup observer on unmount
return () => {
resizeObserver.unobserve(element)
}
}, [element, delayedSetDimensions])

return dimensions
}
import { useEffect, useState } from 'react'
import { useDebouncedCallback } from 'use-debounce'

interface Dimensions {
width: number
height: number
}

export function useDebouncedResizeObserver(element: HTMLElement | null, delay: number): Dimensions {
const [dimensions, setDimensions] = useState<Dimensions>({ width: 0, height: 0 })
const delayedSetDimensions = useDebouncedCallback(setDimensions, delay)

useEffect(() => {
if (!element) return

const resizeObserver = new ResizeObserver((entries) => {
const { width, height } = entries[0].contentRect
delayedSetDimensions(() => ({ width, height }))
})

resizeObserver.observe(element)

// Cleanup observer on unmount
return () => {
resizeObserver.unobserve(element)
}
}, [element, delayedSetDimensions])

return dimensions
}
Here is the usage of the width returned
const [parentElement, setParentElement] = useState<HTMLElement | null>(null)
const { width: parentWidth } = useDebouncedResizeObserver(parentElement, 100)

const CHART_HEIGHT = 200
const CHART_WIDTH = useMemo(() => {
return Math.max(parentWidth - 60, 0)
}, [parentWidth])

...

return (
<div
ref={(e) => {
if (!e) return
setParentElement(e.parentElement)
}}
>
...
<div
style={{
height: CHART_HEIGHT,
width: CHART_WIDTH,
}}
>
const [parentElement, setParentElement] = useState<HTMLElement | null>(null)
const { width: parentWidth } = useDebouncedResizeObserver(parentElement, 100)

const CHART_HEIGHT = 200
const CHART_WIDTH = useMemo(() => {
return Math.max(parentWidth - 60, 0)
}, [parentWidth])

...

return (
<div
ref={(e) => {
if (!e) return
setParentElement(e.parentElement)
}}
>
...
<div
style={{
height: CHART_HEIGHT,
width: CHART_WIDTH,
}}
>
PoppingPopper
PoppingPopper10mo ago
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
Yea, what do you want me to do exactly? Just print the width change out without the graphs present? I think I'm experiencing a cascading effect where the width changes but the child content is choking it between width changes.
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
I'm trying to see if it's possible to get a deployed link but I don't konw yet.
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
The width is definitely being affected by the graphs as I'm only using the responsive width for the graphs. The width is being used like so in my charts
const [parentElement, setParentElement] = useState<HTMLElement | null>(null)
const { width: parentWidth } = useDebouncedResizeObserver(parentElement, 100)

const CHART_HEIGHT = 200
const CHART_WIDTH = useMemo(() => {
return Math.max(parentWidth - 60, 0)
}, [parentWidth])

...

return (
<div
ref={(e) => {
if (!e) return
setParentElement(e.parentElement)
}}
>
...
<div
style={{
height: CHART_HEIGHT,
width: CHART_WIDTH,
}}
>
const [parentElement, setParentElement] = useState<HTMLElement | null>(null)
const { width: parentWidth } = useDebouncedResizeObserver(parentElement, 100)

const CHART_HEIGHT = 200
const CHART_WIDTH = useMemo(() => {
return Math.max(parentWidth - 60, 0)
}, [parentWidth])

...

return (
<div
ref={(e) => {
if (!e) return
setParentElement(e.parentElement)
}}
>
...
<div
style={{
height: CHART_HEIGHT,
width: CHART_WIDTH,
}}
>
PoppingPopper
PoppingPopper10mo ago
I'm listening to the parent container's dimensions
No description
PoppingPopper
PoppingPopper10mo ago
No description
Solution
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
Haha! I am so dumb, I was thinking about what you said
i didnt get why this complexity instead giving w-full to parent
Then I realized I used to have a reason for why I needed to listen to width changes. But not anymore. So I removed all that code and just let the width fill the flex container and its working. <:Laughing_Facepalm:1084929862810222622>
PoppingPopper
PoppingPopper10mo ago
❤️ Thank you @oldcoder
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
@oldcoder How can I mark your message as the answer to this thread?
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
PoppingPopper
PoppingPopper10mo ago
Thanks again!
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
reactibot
reactibot10mo ago
This thread hasn’t had any activity in 36 hours, so it’s now locked. Threads are closed automatically after 36 hours. If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/902647189120118794/1164278522844549177