Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update when @container width changes #18

Open
johnstack94 opened this issue Sep 25, 2024 · 4 comments
Open

Update when @container width changes #18

johnstack94 opened this issue Sep 25, 2024 · 4 comments

Comments

@johnstack94
Copy link

Sometimes the container element is part of changes (eg: react-resizable-panels) without resizing the actual window. It'd be nice for it to update whenever this happens.

@johnstack94
Copy link
Author

I fixed it, I'll create a PR with the proposed fix.

@johnstack94
Copy link
Author

I see that I can't, hence I'll post it here.

Truncate.tsx


// Line 40: Add following ref
...
const resizeObserverRef = useRef<ResizeObserver | null>(null);

...

// Lines 84-101
  useEffect(() => {
    calcTWidth();

    // Create ResizeObserver
    resizeObserverRef.current = new ResizeObserver(() => {
      calcTWidth();
    });

    // Observe the parent element
    if (targetRef.current?.parentElement) {
      resizeObserverRef.current.observe(targetRef.current.parentElement);
    }

    return () => {
      // Cleanup ResizeObserver
      if (resizeObserverRef.current) {
        resizeObserverRef.current.disconnect();
      }

      window.cancelAnimationFrame(animationFrame);
    };
  }, [calcTWidth, animationFrame]);

@johnstack94
Copy link
Author

The following is if you want a debounce so it doesnt react directly.

  const resizeObserverRef = useRef<ResizeObserver | null>(null);
  const resizeTimeoutRef = useRef<number | null>(null);
  
  ...
  
    useEffect(() => {
    calcTWidth();

    // Debounce resize
    const handleResize = () => {
      if (resizeTimeoutRef.current !== null) {
        window.clearTimeout(resizeTimeoutRef.current);
      }
      resizeTimeoutRef.current = window.setTimeout(() => {
        calcTWidth();
      }, 1);
    };

    // Create ResizeObserver
    resizeObserverRef.current = new ResizeObserver(handleResize);

    // Observe the parent element
    if (targetRef.current?.parentElement) {
      resizeObserverRef.current.observe(targetRef.current.parentElement);
    }

    return () => {
      // Cleanup ResizeObserver
      if (resizeObserverRef.current) {
        resizeObserverRef.current.disconnect();
      }

      // Clear any pending timeout
      if (resizeTimeoutRef.current !== null) {
        window.clearTimeout(resizeTimeoutRef.current);
      }

      window.cancelAnimationFrame(animationFrame);
    };
  }, [calcTWidth, animationFrame]);

I found 1ms prevented flashing in my case. However this might be entirely situational.

@chengpeiquan
Copy link
Member

I just finished a busy work and now I am follow up on your issue now.

Thanks for your enthusiastic research. Here I have a simpler implementation. Please refer to whether it can meet your needs.

  1. Set a variable and bind it to the Panel that needs to respond to resize changes, key={refreshKey}
const [refreshKey, setRefreshKey] = useState(Date.now());
  1. When the parent element triggers a resize change, update this value
const onResize = () => setRefreshKey(Date.now());

This makes it easy to re-truncate by React's ability to re-render nodes when a key is updated.

I added a little demo based on the official demo of react-resizable-panels, see: codesandbox

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants