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 triggerhandleResize
.handleResize
callscalculateNextHeight
which can print the height of theEditorBasic
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>
);
}
}
CodePudding user response:
React documents for componentDidUpdate:
Called immediately after updating occurs. Not called for the initial render.
And you are rendering the EditorBasic when showEditorBasic is present and changing its props is simultaneous with the initial rendering.
CodePudding user response:
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>
);
}
}