Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect overflow of React component without ReactDOM?

Basically i want to be able to detect if a react component has children which are overflowing. Just as in this question. I have found that the same thing is possible using ReactDOM, however i cannot/should not use ReactDOM. I don't see anything on the suggested alternative,ref, that is equivalent.

So what i need to know is if it is possible to detect overflow within a react component under these conditions. And to the same point, is it possible to detect width at all?

like image 849
Jemar Jones Avatar asked Feb 02 '17 20:02

Jemar Jones


1 Answers

I needed to achieve this in React TypeScript, as such here is the updated solution in TypeScript using React Hooks. This solution will return true if there are at least 4 lines of text.

We declare the necessary state variables:

  const [overflowActive, setOverflowActive] = useState<boolean>(false);
  const [showMore, setShowMore] = useState<boolean>(false);

We declare the necessary ref using useRef:

  const overflowingText = useRef<HTMLSpanElement | null>(null);

We create a function that checks for overflow:

  const checkOverflow = (textContainer: HTMLSpanElement | null): boolean => {
    if (textContainer)
      return (
        textContainer.offsetHeight < textContainer.scrollHeight || textContainer.offsetWidth < textContainer.scrollWidth
      );
    return false;
  };

Lets build a useEffect that will be called when overflowActive changes and will check our current ref object to determine whether the object is overflowing:

  useEffect(() => {
    if (checkOverflow(overflowingText.current)) {
      setOverflowActive(true);
      return;
    }

    setOverflowActive(false);
  }, [overflowActive]);

In our component's return statement, we need to bind the ref to an appropriate element. I am using Material UI coupled with styled-components so the element in this example will be StyledTypography:

<StyledTypography ref={overflowingText}>{message}</StyledTypography>

Styling the component in styled-components:

const StyledTypography = styled(Typography)({
  display: '-webkit-box',
  '-webkit-line-clamp': '4',
  '-webkit-box-orient': 'vertical',
  overflow: 'hidden',
  textOverflow: 'ellipsis',
});
like image 57
Kraw24 Avatar answered Oct 05 '22 19:10

Kraw24