skip to Main Content

I have a component which take a children as props and render it inside a div which has a callback ref.

const ShowMoreText = (props: ShowLessOrMoreProps) => {
  const { children } = props;

  const [showMore, setShowMore] = useState<boolean>(false);
  const [showButton, setShowButton] = useState<boolean>(false);
  const [childrenHeight, setChildrenHeight] = useState<number>(9.5);

  const measureRef = useCallback((node: HTMLDivElement) => {
    if (node) {
     setChildrenHeight(node.getBoundingClientRect().height);
   }
  }, []);

  useEffect(() => {
   console.log(childrenHeight)// when use measureRef function it gives me 0 when using inline version this gives me correct height and I don't know why
   if (childrenHeight > 45) {
      setShowButton(true);
    }
  }, [childrenHeight]);

  return (
    <Stack
      sx={{
        alignItems: "flex-start",
      }}
    >
      <Collapse in={showMore} collapsedSize={45}>
        <div
          // ref={(node: HTMLDivElement) => {
          //   setChildrenHeight(node?.getBoundingClientRect().height);
          // }}
          ref={() => measureRef} // if I comment this and use the above commmented version everything works fine
        >
          {children}
        </div>
      </Collapse>
      {showButton && ( //when using measureRef function this button won't display
        <Button onClick={() => setShowMore((prev) => !prev)}>
          {showMore ? "Show less" : "Show more"}
        </Button>
      )}
    </Stack>
  );
};

the problem is that when I use stable measureRef function the console log inside useeffect prints 0 but in inline ref version everythings works fine. can anyone explain me why ?

2

Answers


  1. Chosen as BEST ANSWER

    I found the solution and share it here in case anyone is curious or have a same problem. The problem was that the children that I passed to this component was something like this:

    <ShowMoreText>
       <div>{result?.items[0]?.snippet?.description}</div>
    </ShowMoreText>
    

    and because of the delay of request the div height was actually 0 at the beginning. so the actual code for callback ref worked correct and the problem raised because of the api call delay. the solution for me and the mistake that i had been made was not to render the above code conditionally like this:

    {dataIsLoading && 
         <ShowMoreText>
             <div>{result?.items[0]?.snippet?.description}</div>
         </ShowMoreText>
    }
    

    hopefully this can help someone else.


  2. ref={(node: HTMLDivElement) => {
              //   setChildrenHeight(node?.getBoundingClientRect().height);
              // }}
    

    You return a function but ref shoulb be an Object (of certain type)
    Hence You probably return void function.
    if You want to pass (node: HTMLDivElement) => { // setChildrenHeight(node?.getBoundingClientRect().height); // } use unreserved prop then.
    props.ref is reserved for useRef() hook .

    Finally :
    If for some reason Yuu want to save such contruction, do thi that way:

    (node: HTMLDivElement) => {
       return setChildrenHeight(node?.getBoundingClientRect().height);
              }}
    

    Where setChildrenHeight() returns correct object type proper po ref.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search