简体   繁体   中英

How to resize a scrollable list with React Ref's and UseLayoutEffect?

Pretty much in the title. I have a scrollable list that is only scrollable because of the maxHeight: '100vh' line of code. I have a detail card next the list which has accordion components that, when clicked, expand the length of the card and the entire page. The scrollable list however remains locked at its maxHeight of the previous 100vh which at this point only goes up to the middle of the page. Is there a way I can reset the maxHeight with the updated height of the page? Just note I'm using material ui (JSS) for styling.

What I've tried so far:

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;

I used a combination of a custom hook and useRef:

The custom hook:

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

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

  const updateHeight = useCallback(() => {
    if (elementRef && 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;

The component it's used in:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM