In my source code, the height of the component EditorBasic
that I measure by .current.clientHeight
changes when resizing the window, which is not correct. To reproduce the bug, I wrote the following smaller code.
I used aRef
to refer to EditorBasic
and expected to get its height. I expect the following code to have the following behaviour:
When we click on "Click to toggle EditorBasic", by updateTrigger
, EditorBasic
will trigger handleResize
.
handleResize
calls calculateNextHeight
which can print the height of the EditorBasic
so that I could check.
But I cannot pass the 1st step; changing updateTrigger
cannot trigger handleResize
; the log componentDidUpdate
is not printed.
Does anyone know why?
StackBlitz: https://stackblitz.com/edit/react-ts-j4pm8x?file=App.tsx,EditorBasic.tsx
import * as React from 'react';
import EditorBasic from './EditorBasic';
interface IAppProps {}
interface IAppState {
showEditorBasic: boolean;
updateTrigger: number;
}
export default class App extends React.Component<IAppProps, IAppState> {
aRef: any;
constructor(props) {
super(props);
this.state = {
showEditorBasic: false,
updateTrigger: 0,
};
this.aRef = React.createRef();
}
calculateNextHeight = () => {
console.log(
'this.aRef.current.clientHeight',
this.aRef.current.clientHeight
);
};
render() {
return (
<div>
<div
onClick={() =>
this.setState({
showEditorBasic: !this.state.showEditorBasic,
updateTrigger: this.state.updateTrigger + 1,
})
}
>
Click to toggle EditorBasic
</div>
{this.state.showEditorBasic && (
<div ref={this.aRef}>
<EditorBasic
calculateNextHeight={this.calculateNextHeight}
updateTrigger={this.state.updateTrigger}
/>
</div>
)}
</div>
);
}
}
import * as React from 'react';
interface IEditorBasicProps {
calculateNextHeight: any;
updateTrigger;
}
interface IEditorBasicState {}
export default class EditorBasic extends React.Component<
IEditorBasicProps,
IEditorBasicState
> {
handleResize() {
// console.log('handleResize');
this.props.calculateNextHeight();
}
componentDidMount() {
// console.log('componentDidMount');
window.addEventListener('resize', this.handleResize.bind(this));
}
componentDidUpdate(prevProps) {
console.log('componentDidUpdate');
if (this.props['updateTrigger'] !== prevProps['updateTrigger']) {
this.handleResize();
}
}
render() {
return (
<div>
<br />
<br />
EditorBasic {this.props.updateTrigger}
<br />
<br />
</div>
);
}
}
The property showEditorBasic
is completely recreateing the BasicEditor
. In that case, the component will only trigger the componentDidMount
function.
Try to call handleResize
inside componentDidMount
and render the aRef
div outside your if
statement.
App
import * as React from 'react';
import EditorBasic from './EditorBasic';
interface IAppProps {}
interface IAppState {
showEditorBasic: boolean;
updateTrigger: number;
}
export default class App extends React.Component<IAppProps, IAppState> {
aRef: any;
constructor(props) {
super(props);
this.state = {
showEditorBasic: false,
updateTrigger: 0,
};
this.aRef = React.createRef();
}
calculateNextHeight = () => {
console.log(
'this.aRef.current.clientHeight',
this.aRef.current.clientHeight
);
};
render() {
return (
<div>
<div
onClick={() =>
this.setState({
showEditorBasic: !this.state.showEditorBasic,
updateTrigger: this.state.updateTrigger + 1,
})
}
>
Click to toggle EditorBasic
</div>
<div ref={this.aRef}>
{this.state.showEditorBasic && (
<EditorBasic
calculateNextHeight={this.calculateNextHeight}
updateTrigger={this.state.updateTrigger}
/>
)}
</div>
</div>
);
}
}
EditorBasic
import * as React from 'react';
interface IEditorBasicProps {
calculateNextHeight: any;
updateTrigger;
}
interface IEditorBasicState {}
export default class EditorBasic extends React.Component<
IEditorBasicProps,
IEditorBasicState
> {
handleResize() {
// console.log('handleResize');
this.props.calculateNextHeight();
}
componentDidMount() {
// console.log('componentDidMount');
window.addEventListener('resize', this.handleResize.bind(this));
this.handleResize();
}
componentDidUpdate(prevProps) {
console.log('componentDidUpdate');
if (this.props['updateTrigger'] !== prevProps['updateTrigger']) {
this.handleResize();
}
}
render() {
return (
<div>
<br />
<br />
EditorBasic {this.props.updateTrigger}
<br />
<br />
</div>
);
}
}