-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add withSafeTimeout higher-order component
- Loading branch information
Showing
3 changed files
with
89 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
withSafeTimeout | ||
=============== | ||
|
||
`withSafeTimeout` is a React [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html) which provides a special version of `window.setTimeout` which respects the original component's lifecycle. Simply put, a function set to be called in the future via `setSafeTimeout` will never be called if the original component instance ceases to exist in the meantime. | ||
|
||
## Usage | ||
|
||
```jsx | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { withSafeTimeout } from '@wordpress/components'; | ||
|
||
function MyEffectfulComponent( { setSafeTimeout } ) { | ||
return ( | ||
<TextField | ||
onBlur={ () => { | ||
setSafeTimeout( delayedAction, 0 ); | ||
} } | ||
/> | ||
); | ||
} | ||
|
||
export default withSafeTimeout( MyEffectfulComponent ); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { without } from 'lodash'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { Component } from '@wordpress/element'; | ||
|
||
/** | ||
* Browser dependencies | ||
*/ | ||
const { clearTimeout, setTimeout } = window; | ||
|
||
/** | ||
* A higher-order component used to provide and manage delayed function calls | ||
* that ought to be bound to a component's lifecycle. | ||
* | ||
* @param {Component} OriginalComponent Component requiring setTimeout | ||
* | ||
* @return {Component} Wrapped component. | ||
*/ | ||
function withSafeTimeout( OriginalComponent ) { | ||
return class WrappedComponent extends Component { | ||
constructor() { | ||
super( ...arguments ); | ||
this.timeouts = []; | ||
this.setTimeout = this.setTimeout.bind( this ); | ||
this.clearTimeout = this.clearTimeout.bind( this ); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.timeouts.forEach( clearTimeout ); | ||
} | ||
|
||
setTimeout( fn, delay ) { | ||
const id = setTimeout( () => { | ||
fn(); | ||
this.clearTimeout( id ); | ||
}, delay ); | ||
this.timeouts.push( id ); | ||
return id; | ||
} | ||
|
||
clearTimeout( id ) { | ||
clearTimeout( id ); | ||
this.timeouts = without( this.timeouts, id ); | ||
} | ||
|
||
render() { | ||
return ( | ||
<OriginalComponent | ||
{ ...this.props } | ||
setTimeout={ this.setTimeout } | ||
clearTimeout={ this.clearTimeout } | ||
/> | ||
); | ||
} | ||
}; | ||
} | ||
|
||
export default withSafeTimeout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters