Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manipulating DOM in componentDidUpdate #7797

Closed
jvorcak opened this issue Sep 23, 2016 · 3 comments
Closed

Manipulating DOM in componentDidUpdate #7797

jvorcak opened this issue Sep 23, 2016 · 3 comments

Comments

@jvorcak
Copy link

jvorcak commented Sep 23, 2016

Hi, this is more like a question, I'd like to open a discussion regarding DOM manipulation in componentDidUpdate.

I'm creating a React plugin. It has to do some DOM calculations, because CSS is not powerful enough to cover everything this plugin needs to do. The problem is I need to adjust some CSS properties depending on the return value of getBoundingClientRect() of some other DOM element rendered by the same component.

So technically we have 3 options:

  1. Calculate getBoundingClientRect in componentDidUpdate and calling setState with calculated values. I'm afraid of the infinite loop that could happen in certain cases, so I wouldn't go for this one.

  2. Do it like in 1) and play a bit with shouldComponentUpdate, but this seems very complex and not readable. A lot of questions pop up that are dependent on the certain use case.

  3. Update DOM from componentDidUpdate. This is the solution I decided to go for, it works, it's simple, stable and works as intended. However I feel I'm on the edge, so I wanted to double check that this is an OK way of doing things. Is it OK to manipulate DOM in componentDidUpdate? It's called everytime render is done, and I'm OK with throwing away my changes, because for next render I'll modify DOM again.

Here's a part of the code

componentDidMount() {
  this.recalculateIndent();
}

componentDidUpdate() {
  this.recalculateIndent();
}

recalculateIndent() {
  // calculate indent based on getBoundingClientRect of some DOM reference
  this.textareaRef.style.textIndent = `${indent}px`;
}

render() {
   return (
   ...
   <textarea ref={ref => this.textareaRef = ref}/>
   ...
   );
}
@jvorcak jvorcak changed the title Updating DOM after render Updating DOM after componentDidUpdate Sep 23, 2016
@jvorcak jvorcak changed the title Updating DOM after componentDidUpdate Manipulating DOM in componentDidUpdate Sep 23, 2016
@karczk
Copy link
Contributor

karczk commented Sep 23, 2016

Each solution (component lifecycle method) is proper for concrete situation, but DOM manipulation is wrong. Use state and re-render component. Example for my last use case "fixed header for table + virtual scrolling for table body", I hope this will help you understand the correct flow.

  1. Component constructor: initial state value: bodyHeight = 0 (or null, as you like).
  2. First render, renders table header but empty table body (0 rows).
  3. componentDidMount - read header and container DOM height (+ some calculation...) and setState for bodyHeight (re-render).
  4. Second render, bodyHeight !== 0, table body will be rendered. Now, height parameter is known (I can set it using "style" component prop, rather than DOM manipulation), I can add components for rows.
  5. Additional event listener for "resize" (document/browser resize), add in componentDidMount, remove in componentWillUnmount. In event handler I do the same thing like in componentDidMount - read new DOM height values and setState.
  6. There is no DOM manipulation by hand, react does the job.

@aweary
Copy link
Contributor

aweary commented Sep 27, 2016

@jvorcak using componentDidUpdate is the correct place to manipulate the DOM manually after a render. Per the docs:

Use this as an opportunity to operate on the DOM when the component has been updated.

Also, we try to use the issue tracker solely for feature requests and bug reports. Usage questions should be directed elsewhere, like discuss.reactjs.org or StackOverflow. Thanks!

@aweary aweary closed this as completed Sep 27, 2016
@Juanmasoa
Copy link

What if you want to update one Component after changing something in another?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants