Resizing a scrollable list using React Refs and UseLayoutEffect

Essentially, my issue stems from having a scrollable list with a set maximum height of '100vh'. I also have a detail card beside the list that contains accordion components. When one of these accordions is expanded, it increases the height of the card and subsequently the entire page. However, the scrollable list remains locked at its original maxHeight of 100vh, which now only reaches halfway down the page. Is there a way to dynamically reset the maxHeight based on the updated page height? It's important to note that I am using material ui (JSS) for styling.

My current approach:

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;

Answer №1

I implemented a solution utilizing a custom hook in conjunction with the useRef feature:

The custom hook code snippet is as follows:

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 where this custom hook is utilized looks like this:

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;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to compare all the elements in an array to the entries in another object, while also storing the results of each comparison?

I am working with a JSON file that contains an array of 2 objects: `{ bg: 'a', o: 'c' }`, `{hg': 'a2', 'oo': 'c3'}`. My goal is to compare each object in the array with another object structured as fol ...

Problems with navigation alignment in Flask website due to HTML, CSS, and

Here's a snapshot of my current website design: website I'm attempting to place the Login & Sign up buttons in line with the rest of the navigation bar. I've tried various methods without success so far. My attempts include adjusting text a ...

AgGrid Encounters Difficulty in Recovering Original Grid Information

After making an initial API call, I populate the grid with data. One of the fields that is editable is the Price cell. If I edit a Price cell and then click the Restore button, the original dataset is restored. However, if I edit a Price cell again, the ...

Whenever I try to log in using axios and my credentials are incorrect, I don't receive any response back in the catch block

I cannot receive any response when calling the login API from Node.js. In the frontend, I am handling the catch as well. How do I retrieve the Invalid Credentials message from the backend API if the credentials do not match? The code for my backend logi ...

Are there any find all functions available in JavaScript that are built-in?

I frequently work with arrays in JavaScript, and I am facing an issue with the function .find() as it only returns the first occurrence. I need a way to get all occurrences if there are multiple. Below is my code: const condition = [ { info_p ...

Tips for accessing the parent method within a jQuery AJAX success function

Similar Question: javascript how to reference parent element Hello everyone! This is my first time posting here. I have a question - how can I trigger alerts from a successful AJAX call? var page = { alerts: function (json) { if (json ...

Ensure the header remains fixed when scrolling in an HTML page with Bootstrap

I created the following code. However, when I scroll down the table, the header disappears from view. I would like the header to always remain at the top, even when scrolling. Despite searching Google multiple times and trying various solutions, I have no ...

Building upon a React component with TypeScript, we are extending its functionality using a generic type and then leveraging this same generic type

In my component, I have a setup where it takes two props - node and patchCurrentNode. import { css } from '@emotion/react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React, { PropsWithChildren, useStat ...

How to solve a React Native CLI QuickStart error?

I'm currently working on my first React Native app, but I've encountered a problem: ✖ Issue with Bundler Installation error: It seems that the extensions for executable-hooks-1.6.1 are not built properly. Please try running "gem pristine execut ...

Is there a way to output several lines from a JSON file in print form?

I'm working with HTML code that displays multiple lines from a JSON file, but it only shows one line at a time. How can I modify the code to display all users' information? <!DOCTYPE html> <html> <head> <script> function ...

Using CSS to enforce a specific height for text by overflowing its parent container horizontally

I have a lengthy phrase that takes up too much space on mobile devices. Here is an example: .artificial-phone-viewport { width: 320px; height: 500px; border: 1px solid darkgrey; } .container { width: 100%; height: 100%; } .text { /* * Do ...

Posts created in Express using the node-postgres module are not being retrieved by queries in async routes

Running a basic query from an express route seems to be causing some issues for me: var router = require('express-promise-router')() const { Pool } = require('pg') const pool = new Pool({ user: 'user', password: 'pa ...

Material UI's Paper component is not expanding to full width when viewed on a smaller screen size

I'm currently working on a website project and utilizing a component for displaying dark mode. However, I've encountered an issue where the Component shrinks excessively when the screen size goes below 600px, unlike other components. This is a s ...

Preventing a JavaScript timer function from executing multiple times when triggered by an 'in viewport' function

I am trying to create a website feature where a timer starts counting up once a specific div is scrolled into view. However, I am encountering an issue where scrolling away restarts the timer, and I would like the final value that the timer reaches to rema ...

What could be causing the function to not work properly within the React component?

Having trouble with a React component utilizing speech recognition for converting speech to text. Initialized the recognition functions within the component but encountering errors. Need assistance in troubleshooting this issue. const speechRecognition = w ...

Is it possible to create multiple text input components using the "each" function, and how can I update the state by combining all of them together?

I am looking to create a text-based word game where the length of each word changes with every level. Each letter will be placed in its own box, forming a matrix (e.g. 10 words, length: 10 => 10x10 matrix). How can I generate multiple text input compone ...

Encountering an error stating 'ReadableStream is not defined' while attempting to log in using Discord on the NextAuth application

While attempting to set up a Discord sign-in page to test NextAuth on my website, I encountered the error ReferenceError: ReadableStream is not defined. After examining the stack trace, it seems to be related to how my packages are configured, but I' ...

Is it possible to use the React Context API within the getInitialProps, getServerSideProps, or getStaticProps functions

Is there a way to invoke an action creator using the React Context API within getInitialProps/getServerSideProps/getStaticProps of NextJs? When working with Redux and NextJs, it is straightforward to access the store and dispatch an action creator. Howeve ...

What causes React JS to continuously render in an infinite loop when using hooks and useState

I am struggling with updating the current state of my component based on a result using a custom hook in React. Whenever I try to update it, I end up in an infinite loop rendering due to my usage of the useState() hook. I am still new to working with Rea ...

transform a zipped file stream into a physical file stored on the disk

I have a Node application named MiddleOne that communicates with another Node App called BiServer. BiServer has only one route set up like this: app.get("/", (req, res) => { const file = `./zipFiles.zip`; return res.download(file); }); When Middl ...