I know that calling setState() immediately in componentDidMount() is a performance issue and it is better to use the constructor in some cases.
But in the last sentence of the React documentation it talks about a USE CASE that states that calling setState() immediately in componentDidMount() if it is VIABLE, what does THAT USE CASE mean.
Documentation React:
You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in the constructor() instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
I would like an simple example (with code), PLEASE, because I have not been able to see it in words alone
CodePudding user response:
Sometimes you might need access to the DOM elements managed by React—for example, to focus a node, scroll to it, or measure its size and position. There is no built-in way to do those things in React, so you will need a ref to the DOM node. During the first render, the DOM nodes have not yet been created, so ref.current will be null. And during the rendering of updates, the DOM nodes haven’t been updated yet. So it’s too early to read them. This is why sometimes you have to wait to read ref and set state in componentDidMount, or in useEffect for functionnal components
Example to get the height of an element:
class DivSize extends Component {
constructor(props) {
super(props)
this.state = {
height: 0
}
}
componentDidMount() {
const height = this.divElement.clientHeight;
this.setState({ height });
}
render() {
return (
<div
ref={ (divElement) => { this.divElement = divElement } }
>
Size: <b>{this.state.height}px</b> but it should be 18px after the render
</div>
)
}
}