Skip to content

Commit

Permalink
Fixed component double rendering in StrictMode
Browse files Browse the repository at this point in the history
  • Loading branch information
psmyrek committed May 18, 2022
1 parent d680f5d commit ce59dc5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 27 deletions.
36 changes: 24 additions & 12 deletions src/ckeditor.jsx
Expand Up @@ -92,24 +92,30 @@ export default class CKEditor extends React.Component {

/**
* Initialize the editor when the component is mounted.
*
* @returns {Promise}
*/
componentDidMount() {
this._initializeEditor();
async componentDidMount() {
await this._initializeEditor();
}

/**
* Re-render the entire component once again. The old editor will be destroyed and the new one will be created.
*
* @returns {Promise}
*/
componentDidUpdate() {
this._destroyEditor();
this._initializeEditor();
async componentDidUpdate() {
await this._destroyEditor();
await this._initializeEditor();
}

/**
* Destroy the editor before unmounting the component.
*
* @returns {Promise}
*/
componentWillUnmount() {
this._destroyEditor();
async componentWillUnmount() {
await this._destroyEditor();
}

/**
Expand All @@ -127,8 +133,13 @@ export default class CKEditor extends React.Component {
* Initializes the editor by creating a proper watchdog and initializing it with the editor's configuration.
*
* @private
* @returns {Promise}
*/
_initializeEditor() {
async _initializeEditor() {
if ( this.watchdog ) {
return;
}

if ( this.context instanceof ContextWatchdog ) {
this.watchdog = new EditorWatchdogAdapter( this.context );
} else {
Expand All @@ -141,7 +152,7 @@ export default class CKEditor extends React.Component {
this.props.onError( error, { phase: 'runtime', willEditorRestart: causesRestart } );
} );

this.watchdog.create( this.domContainer.current, this._getConfig() )
await this.watchdog.create( this.domContainer.current, this._getConfig() )
.catch( error => this.props.onError( error, { phase: 'initialization', willEditorRestart: false } ) );
}

Expand Down Expand Up @@ -205,15 +216,16 @@ export default class CKEditor extends React.Component {
* Destroys the editor by destroying the watchdog.
*
* @private
* @returns {Promise}
*/
_destroyEditor() {
async _destroyEditor() {
// It may happen during the tests that the watchdog instance is not assigned before destroying itself. See: #197.
/* istanbul ignore next */
if ( !this.watchdog ) {
if ( !this.editor ) {
return;
}

this.watchdog.destroy();
await this.watchdog.destroy();
this.watchdog = null;
}

Expand Down
30 changes: 15 additions & 15 deletions src/ckeditorcontext.jsx
Expand Up @@ -20,20 +20,20 @@ export default class CKEditorContext extends React.Component {
}
}

shouldComponentUpdate( nextProps ) {
async shouldComponentUpdate( nextProps ) {
// If the configuration changes then the ContextWatchdog needs to be destroyed and recreated
// On top of the new configuration.
if ( nextProps.id !== this.props.id ) {
/* istanbul ignore else */
if ( this.contextWatchdog ) {
this.contextWatchdog.destroy();
await this.contextWatchdog.destroy();
}

this._initializeContextWatchdog( nextProps.config );
await this._initializeContextWatchdog( nextProps.config );
}

if ( nextProps.isLayoutReady && !this.contextWatchdog ) {
this._initializeContextWatchdog( nextProps.config );
await this._initializeContextWatchdog( nextProps.config );

return true;
}
Expand All @@ -50,21 +50,13 @@ export default class CKEditorContext extends React.Component {
);
}

componentWillUnmount() {
this._destroyContext();
async componentWillUnmount() {
await this._destroyContext();
}

_initializeContextWatchdog( config ) {
async _initializeContextWatchdog( config ) {
this.contextWatchdog = new ContextWatchdog( this.props.context );

this.contextWatchdog.create( config )
.catch( error => {
this.props.onError( error, {
phase: 'initialization',
willContextRestart: false
} );
} );

this.contextWatchdog.on( 'error', ( _, errorEvent ) => {
this.props.onError( errorEvent.error, {
phase: 'runtime',
Expand All @@ -77,6 +69,14 @@ export default class CKEditorContext extends React.Component {
this.props.onReady( this.contextWatchdog.context );
}
} );

await this.contextWatchdog.create( config )
.catch( error => {
this.props.onError( error, {
phase: 'initialization',
willContextRestart: false
} );
} );
}

async _destroyContext() {
Expand Down

0 comments on commit ce59dc5

Please sign in to comment.