Altering the DOM directly within the componentDidMount() lifecycle method without needing to use

In ReactJS, I am facing an issue while trying to manipulate the DOM in the componentDidMount() method. The problem lies in the fact that the DOM is not fully rendered at this point, requiring me to use a setTimeout function, which I find undesirable.

Upon logging the scrollHeight of the rendered element in componentDidMount(), I noticed that it returns a different value compared to when I introduce a delay of let's say 100 milliseconds.

My objective is to automatically scroll down to the bottom of an element as discussed in this resource How to scroll to bottom in react?

The component in question is a modal window that displays the children of another component using {this.props.children}. Initially, the modal window is set with visibility: hidden and opacity: 0, matching the height of the window when first appearing on the page. Upon clicking a button, it becomes visible but retains the initial window height until a few milliseconds have passed.

I suspect there may be an error in my implementation as the use of setTimeout indicates, although I have not yet identified it.

I also attempted to make DOM changes in the componentDidUpdate() method without success.

This is the code snippet from the modal-window component:

componentDidMount() {
  console.log(document.querySelector('.myModal').scrollHeight);
  setTimeout(function() {
    console.log(document.querySelector('.myModal').scrollHeight);
  }, 100);
}

The first console.log output shows, for example, 497, whereas the second one reveals approximately 952.

Update

In my modal-window component, I render a child component like so, such as for my inbox-thread:

<Modal>
  <InboxThread />
</Modal>

The issue was resolved by waiting for the modal-window component to render its children, achieved by adjusting the Modal.js file as follows:

render() {
    return (
      <React.Fragment>
        {this.props.children}
      </React.Fragment>
    );
  }

Ultimately, I managed to solve the problem by passing a method through props from the parent component where I called the modal to check componentDidUpdate() in Modal.js.

The code now appears as follows in the parent component:

...
export default class InboxThreadList extends React.Component {
  constructor(props) {
    super(props);
    this.scrollToModalBottom = this.scrollToModalBottom.bind(this);
  }
  render() {
    return (
    <React.Fragment>
      ...
      <Modal onRender={this.scrollToModalBottom}>
        <InboxThread/>
      </Modal>
    </React.Fragment>
    )
  }
  scrollToModalBottom() {
    const myModalObject = document.querySelector('.myModal');
    myModalObject.scrollTop = myModalObject.scrollHeight;
  }
}

And in the Modal.js file:

...
export default class Modal extends React.Component {
  ...
  componentDidUpdate() {
    if ('onRender' in this.props) {
      this.props.onRender();
    }
  }
  render() {
    return (
      <div className={'myModal'}>
        {this.props.children}
      </div>
    );
  }

I acknowledge the need to transition to using refs instead of document.querySelector, which can be implemented according to this guidance React - Passing ref from dumb component(child) to smart component(parent).

Answer №1

When utilizing a ref, ensure that the element is consistently rendered in the render() method to guarantee resolution before componentDidMount gets executed:

componentDidMount() {
  // able to utilize any refs here
}

componentDidUpdate() {
  // able to utilize any refs here
}

render() {
  // as long as those refs were rendered!
  return <div ref={/* ... */} />;
}

componentDidMount called BEFORE ref callback

In your scenario, you could implement it similarly to this:

componentDidMount() {
  console.log(this.modalElement.scrollHeight)
}

render() {
 return <div className="modal" ref={ref => this.modalElement = ref} />
}

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

Why is it necessary to use "new" with a Mongoose model in TypeScript?

I'm a bit confused here, but let me try to explain. When creating a new mongoose.model, I do it like this: let MyModel = moongoose.model<IMyModel>("myModel", MyModelSchema); What exactly is the difference between MyModel and let newModel = ne ...

Having trouble validating array length with Yup (using Formik and React)

Just joined Yup and struggling to validate an array that is not empty. My tech stack includes react, formik, yup, and material-ui. Here's a sample I put together: Check out the example here I attempted to use the required method in validationSchem ...

Using Ternary Operators in React Components for Styling

Extracting data from a json file and attempting to assign a specific class only when certain criteria are met: render: function() { var gameList = this.props.data.map(function(game) { return ( <li key={game.id} className="l ...

Transitioning Menus with Submenu Animation

After following a CSS menu tutorial and customizing it, two issues have arisen. When hovering over the "About" menu with additional list links, the transition works but then the content shifts to the left and fades out. The second issue is related to tryin ...

Using Node http-middleware-proxy and integrating it with Express to communicate with Tomcat server

We have set up our Java application (which is spring based) in a Tomcat container, with the UI modules also running in the same environment. When we access Tomcat directly through http://localhost:8080, a login page is displayed and then a 302 redirect occ ...

Expanding Grid Container in Material UI to Fill Parent Height and Width

Challenge I'm struggling to figure out how to make a Grid container element expand to the height and width of its parent element without directly setting the dimensions using inline styles or utilizing the makeStyles/useStyles hook for styling. I&ap ...

Upon hovering, icons for each project name are displayed when `mouseenter` event is triggered

My issue lies with the mouseenter function. I am trying to display icons specific to the project name I hover over, but currently, it displays icons for all projects at once. I want each project hovered over to show me its respective icons Below is some c ...

React error: The module "react-router-dom" does not have a member named "useNavigate" available for export

I'm attempting to include useNavigate for use as outlined in the top answer here: react button onClick redirect page import { useNavigate } from "react-router-dom"; However, I am encountering this error: export 'useNavigate' (impo ...

Is it possible for the outcome of a component to be passed to render and actually show up as undefined

I am currently working on creating a wrapper component for an API call in order to display "loading" if the API hasn't updated yet. As I am new to React, I am struggling with passing the state to the ApiResp component: After checking the console.log ...

Has the querystring hack become outdated?

For a long time, I have been adding a query string to my CSS link whenever I made changes that needed to be reflected on client machines: <link href="/Resources/styles/styles.css?v=1" rel="stylesheet" /> Lately, I've noticed that Chrome seems ...

Encountering an error following the deployment of the React application to Azure

My react application was successfully deployed on azure using a windows environment. However, upon trying to access the website, I encountered the following error message: "You do not have permission to view this directory or page." Even after adding the ...

The dilemma of using styled-components for styling in Material-UI

I find myself a bit puzzled by the various ways Material UI offers for styling. My goal is to maintain a consistent styling API throughout the entire app. However, I would also appreciate having some styled-components-like styles for certain global compone ...

Error: Unable to access attributes of an undefined object (looking for 'item')

Every time I attempt to execute the following code, I encounter this error. import React from 'react' import { Accordion} from 'react-bootstrap/Accordion'; import { ToastContainer } from 'react-toastify'; const myaccordion = ( ...

The HTML select element - Styling the selected item using the option font

Currently, I am working on adding a font dropdown list to a web page. Each option in the dropdown list is styled with the corresponding font it represents like this:- <option value="Arial, Helvetica, sans-serif" style="font-family: Arial,Helvetica,sans ...

Could someone assist me in figuring out the reason behind my fetch method sending undefined values?

Looking for some assistance with my fetch implementation issue. I am currently working on integrating stripe into my online grocery store website utilizing a node.js server with express, and ejs for frontend integration. The client-side JavaScript uses a f ...

Unable to retrieve information from compact JSON files

It's been 2 hours and I still can't figure this out I need help with reading my Json Data in my JavaScript File, saving it to a variable, and then printing it out. I've tried multiple solutions but nothing seems to work (I'm new to ...

Encountering difficulty displaying image in browser from the public/assets directory in Next.js

Here is the code I have written: import Image from "next/image"; import React from "react"; import { ProcessImg } from "../public/assets/process_img.png"; <Image className="lg:w-3/5 md:w-1/2 obj ...

Error when customizing the text of Material UI CardHeader component

Looking to customize the appearance of your CardHeader text? Check out how you can utilize the title and titleTypographyProps props. For more information, refer to Material UI API documentation: Api Doc Take a glance at the code in this sample sandbox: H ...

Ways to release a client-side script with npm?

Within my nodejs package, I have included code that can be executed on both the backend and in a single .js file for browsers. In order to utilize the browser script, it must be placed within a script element in an HTML file. My query pertains to whether t ...

It is not possible to include a new property to an object while inside a function

Looking to add a property to an object? Check out the code below: import React from 'react'; import { Link } from 'react-router-dom'; const Question = () => { let active; const handleClick = (iconName) => { active = {}; ...