Skip to content

Commit

Permalink
Components: Mimic URLInput request abort on fetch (#8049)
Browse files Browse the repository at this point in the history
* Components: Mimic URLInput request abort on fetch

* Components: Compare URLInput request by reference

* Components: Remove unused includes import
  • Loading branch information
aduth committed Jul 19, 2018
1 parent 6efbcfb commit 348e463
Showing 1 changed file with 55 additions and 53 deletions.
108 changes: 55 additions & 53 deletions editor/components/url-input/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,41 @@ const stopEventPropagation = ( event ) => event.stopPropagation();
class URLInput extends Component {
constructor() {
super( ...arguments );

this.onChange = this.onChange.bind( this );
this.onKeyDown = this.onKeyDown.bind( this );
this.bindListNode = this.bindListNode.bind( this );
this.updateSuggestions = throttle( this.updateSuggestions.bind( this ), 200 );

this.suggestionNodes = [];

this.state = {
posts: [],
showSuggestions: false,
selectedSuggestion: null,
};
}

componentDidUpdate() {
const { showSuggestions, selectedSuggestion } = this.state;
// only have to worry about scrolling selected suggestion into view
// when already expanded
if ( showSuggestions && selectedSuggestion !== null && ! this.scrollingIntoView ) {
this.scrollingIntoView = true;
scrollIntoView( this.suggestionNodes[ selectedSuggestion ], this.listNode, {
onlyScrollIfNeeded: true,
} );

setTimeout( () => {
this.scrollingIntoView = false;
}, 100 );
}
}

componentWillUnmount() {
delete this.suggestionsRequest;
}

bindListNode( ref ) {
this.listNode = ref;
}
Expand All @@ -49,10 +72,6 @@ class URLInput extends Component {
}

updateSuggestions( value ) {
if ( this.suggestionsRequest ) {
this.suggestionsRequest.abort();
}

// Show the suggestions after typing at least 2 characters
// and also for URLs
if ( value.length < 2 || /^https?:/.test( value ) ) {
Expand All @@ -70,41 +89,46 @@ class URLInput extends Component {
selectedSuggestion: null,
loading: true,
} );
this.suggestionsRequest = apiFetch( {

const request = apiFetch( {
path: `/wp/v2/posts?${ stringify( {
search: value,
per_page: 20,
orderby: 'relevance',
} ) }`,
} );

this.suggestionsRequest
.then(
( posts ) => {
this.setState( {
posts,
loading: false,
} );
request.then( ( posts ) => {
// A fetch Promise doesn't have an abort option. It's mimicked by
// comparing the request reference in on the instance, which is
// reset or deleted on subsequent requests or unmounting.
if ( this.suggestionsRequest !== request ) {
return;
}

if ( !! posts.length ) {
this.props.debouncedSpeak( sprintf( _n(
'%d result found, use up and down arrow keys to navigate.',
'%d results found, use up and down arrow keys to navigate.',
posts.length
), posts.length ), 'assertive' );
} else {
this.props.debouncedSpeak( __( 'No results.' ), 'assertive' );
}
},
( xhr ) => {
if ( xhr.statusText === 'abort' ) {
return;
}
this.setState( {
loading: false,
} );
}
);
this.setState( {
posts,
loading: false,
} );

if ( !! posts.length ) {
this.props.debouncedSpeak( sprintf( _n(
'%d result found, use up and down arrow keys to navigate.',
'%d results found, use up and down arrow keys to navigate.',
posts.length
), posts.length ), 'assertive' );
} else {
this.props.debouncedSpeak( __( 'No results.' ), 'assertive' );
}
} ).catch( () => {
if ( this.suggestionsRequest === request ) {
this.setState( {
loading: false,
} );
}
} );

this.suggestionsRequest = request;
}

onChange( event ) {
Expand Down Expand Up @@ -158,28 +182,6 @@ class URLInput extends Component {
} );
}

componentWillUnmount() {
if ( this.suggestionsRequest ) {
this.suggestionsRequest.abort();
}
}

componentDidUpdate() {
const { showSuggestions, selectedSuggestion } = this.state;
// only have to worry about scrolling selected suggestion into view
// when already expanded
if ( showSuggestions && selectedSuggestion !== null && ! this.scrollingIntoView ) {
this.scrollingIntoView = true;
scrollIntoView( this.suggestionNodes[ selectedSuggestion ], this.listNode, {
onlyScrollIfNeeded: true,
} );

setTimeout( () => {
this.scrollingIntoView = false;
}, 100 );
}
}

render() {
const { value = '', autoFocus = true, instanceId } = this.props;
const { showSuggestions, posts, selectedSuggestion, loading } = this.state;
Expand Down

0 comments on commit 348e463

Please sign in to comment.