Skip to content

Commit

Permalink
compose: Add types useAsyncList (#31523)
Browse files Browse the repository at this point in the history
* compose: Add types useAsyncList

* Add missing type references

* Implement promosed simplification
  • Loading branch information
sarayourfriend authored May 7, 2021
1 parent 054ff5a commit 54fdd28
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 38 deletions.
4 changes: 2 additions & 2 deletions packages/compose/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ This behavior is useful if we want to render a list of items asynchronously for

_Parameters_

- _list_ `Array`: Source array.
- _list_ `T[]`: Source array.

_Returns_

- `Array`: Async array.
- `T[]`: Async array.

<a name="useConstrainedTabbing" href="#useConstrainedTabbing">#</a> **useConstrainedTabbing**

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/**
* WordPress dependencies
*/
import { useEffect, useReducer } from '@wordpress/element';
import { useEffect, useState } from '@wordpress/element';
import { createQueue } from '@wordpress/priority-queue';

/**
* Returns the first items from list that are present on state.
*
* @param {Array} list New array.
* @param {Array} state Current state.
* @return {Array} First items present iin state.
* @param list New array.
* @param state Current state.
* @return First items present iin state.
*/
function getFirstItemsPresentInState( list, state ) {
function getFirstItemsPresentInState< T >( list: T[], state: T[] ): T[] {
const firstItems = [];

for ( let i = 0; i < list.length; i++ ) {
Expand All @@ -26,49 +26,27 @@ function getFirstItemsPresentInState( list, state ) {
return firstItems;
}

/**
* Reducer keeping track of a list of appended items.
*
* @param {Array} state Current state
* @param {Object} action Action
*
* @return {Array} update state.
*/
function listReducer( state, action ) {
if ( action.type === 'reset' ) {
return action.list;
}

if ( action.type === 'append' ) {
return [ ...state, action.item ];
}

return state;
}

/**
* React hook returns an array which items get asynchronously appended from a source array.
* This behavior is useful if we want to render a list of items asynchronously for performance reasons.
*
* @param {Array} list Source array.
* @return {Array} Async array.
* @param list Source array.
* @return Async array.
*/
function useAsyncList( list ) {
const [ current, dispatch ] = useReducer( listReducer, [] );
function useAsyncList< T >( list: T[] ): T[] {
const [ current, setCurrent ] = useState( [] as T[] );

useEffect( () => {
// On reset, we keep the first items that were previously rendered.
const firstItems = getFirstItemsPresentInState( list, current );
dispatch( {
type: 'reset',
list: firstItems,
} );
setCurrent( firstItems );

const asyncQueue = createQueue();
const append = ( index ) => () => {
const append = ( index: number ) => () => {
if ( list.length <= index ) {
return;
}
dispatch( { type: 'append', item: list[ index ] } );
setCurrent( ( state ) => [ ...state, list[ index ] ] );
asyncQueue.add( {}, append( index + 1 ) );
};
asyncQueue.add( {}, append( firstItems.length ) );
Expand Down
7 changes: 6 additions & 1 deletion packages/compose/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types"
"declarationDir": "build-types",
},
"references": [
{ "path": "../element" },
{ "path": "../priority-queue" },
],
"include": [
"src/higher-order/if-condition/**/*",
"src/higher-order/pure/**/*",
"src/higher-order/with-instance-id/**/*",
"src/hooks/use-async-list/**/*",
"src/hooks/use-instance-id/**/*",
"src/utils/**/*"
]
Expand Down

0 comments on commit 54fdd28

Please sign in to comment.