Как изменить размер прокручиваемого списка с помощью React Ref и useLayoutEffect?

#javascript #css #reactjs #react-hooks #material-ui

#javascript #css #reactjs #реагирующие хуки #материал-пользовательский интерфейс

Вопрос:

В значительной степени в названии. У меня есть прокручиваемый список, который можно прокручивать только из-за maxHeight: '100vh' строки кода. Рядом со списком у меня есть подробная карточка, в которой есть компоненты аккордеона, которые при нажатии увеличивают длину карточки и всей страницы. Однако прокручиваемый список остается заблокированным на максимальной высоте предыдущего 100vh, которая на данный момент доходит только до середины страницы. Есть ли способ сбросить максимальную высоту с обновленной высотой страницы? Просто обратите внимание, что я использую material ui (JSS) для стилизации.

Что я пробовал до сих пор:

 const List = ({ match }) => {
  
  const [height, setHeight] = useState(0)
  const ref = useRef(null)

  console.log(ref)
  

  
  useLayoutEffect(() => {
    setHeight(ref.current.clientHeight) 
  }, [])

  
  return (
    <div className={classes.root}>
     
        <Grid container justify="center" >
          <Grid item xs={10} className={classes.filter}>
            {renderFilter()}
          </Grid>
        </Grid>
        <Grid container justify='center' className={classes.cardGrid}>
        {!matches ? <Grid item xs={3} md={3} lg={3} style={{maxHeight: Math.max(height, '100vh')}} className={classes.list}>
            <List>{renderedList()}</List>  
        </Grid> : drawer}
        <Grid item lg={1} md={1} sm={0} xs={0}/>
        <Grid item xs={10} md={6} lg={6}  ref={ref} className={classes.detail}>
          {renderDetail()}
        </Grid>
    
        </Grid>
    </div>
  );
};

export default SongList;
 

Ответ №1:

Я использовал комбинацию пользовательского хука и useRef:

Пользовательский хук:

 import { useState, useEffect, useCallback } from "react";

function useHeight(elementRef) {
  const [height, setHeight] = useState(null);

  const updateHeight = useCallback(() => {
    if (elementRef amp;amp; elementRef.current) {
      const { height } = elementRef.current.getBoundingClientRect();
      setHeight( height);
      
    }
  }, [elementRef]);

  useEffect(() => {
    updateHeight();
    window.addEventListener("transitionstart", updateHeight);
    return () => {
      window.removeEventListener("transitionstart", updateHeight);
    };
  }, [updateHeight]);
  return [height];
}

export default useHeight;
 

Компонент, в котором он используется:

 const List = ({ match }) => {
  const elementDOM = useRef(null);
  const [height] = useHeight(elementDOM);

  
  return (
    <div className={classes.root}>
     
        <Grid container justify="center" >
          <Grid item xs={10} className={classes.filter}>
            {renderFilter()}
          </Grid>
        </Grid>
        <Grid container justify='center' className={classes.cardGrid}>
        {!matches ? <Grid item xs={3} md={3} lg={3}  className={classes.list}>
            <List style={{minHeight: '100vh', height: height}}>{renderedList()}</List>  
        </Grid> : drawer}
        <Grid item lg={1} md={1} sm={0} xs={0}/>
        <Grid item xs={10} md={6} lg={6}  ref={elementDOM} className={classes.detail}>
          {renderDetail()}
        </Grid>
    
        </Grid>
    </div>
  );
};

export default SongList;