Andarist / react-textarea-autosize

<textarea /> component for React which grows with content
http://andarist.github.io/react-textarea-autosize/
MIT License
2.22k stars 246 forks source link

Doesn't update if made to change width without re-rendering #389

Open Macil opened 1 year ago

Macil commented 1 year ago

Here's a codesandbox demo:

https://codesandbox.io/s/react-textarea-autosize-bug-2hc6yv

If you press the "Toggle sidebar" button, then the textarea gets squished by the expanding sidebar and fails to become taller to account for the further-wrapped text.

A fix would be to use ResizeObserver specifically to track changes to the element's width. ResizeObservers have had support on all popular browsers since 2020.

The window resize listener at https://github.com/Andarist/react-textarea-autosize/blob/896596a5a9ab02d566f528442758a43633843481/src/index.tsx#L101 would be unnecessary if a useLayoutEffect call like this was present there instead which set up the ResizeObserver:

React.useLayoutEffect(() => {
  // monitor for changes to width
  if (globalThis.ResizeObserver) {
    let knownWidth = libRef.current.clientWidth;
    const ro = new ResizeObserver((entries) => {
      const newWidth = entries[entries.length-1].contentRect.width;
      if (newWidth !== knownWidth) {
        knownWidth = newWidth;
        resizeTextarea();
      }
    });
    ro.observe(libRef.current);
    return () => {
      ro.disconnect();
    };
  }
}, []);

Additionally, even though issue https://github.com/Andarist/react-textarea-autosize/issues/337 isn't really this library's fault, using a ResizeObserver would work around that issue as it would get triggered as soon as the textarea is inserted into the document.

shakti97 commented 10 months ago

@Andarist I am also facing a similar issue; once its width changes, it doesn't adjust the rows accordingly. When can we expect this to be fixed, or would you like me to raise a pull request to address it?

Andarist commented 10 months ago

A PR is always appreciated but I can't promise that I will actually have time to review this. The fact that we don't quite have automated tests here doesn't help 😢

stephenasuncionDEV commented 3 months ago

Ended up forcing rerender on focus, but still need this to be automatic

Another work around:

const [forceUpdate] = useForceUpdate();
// work around for https://github.com/Andarist/react-textarea-autosize/issues/389
  useEffect(() => {
    const _forceRerender = async () => {
      await new Promise((resolve) => setTimeout(resolve, 100));
      forceUpdate();
    };
    _forceRerender();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isMobile]);