From 7b9169d78960d3bfc4aa7b0df51025cb08cdc87b Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Wed, 5 May 2021 14:04:56 -0700 Subject: [PATCH 1/3] compose: Add types useAsyncList --- packages/compose/README.md | 4 +- .../use-async-list/{index.js => index.ts} | 42 +++++++++++++------ packages/compose/tsconfig.json | 1 + 3 files changed, 32 insertions(+), 15 deletions(-) rename packages/compose/src/hooks/use-async-list/{index.js => index.ts} (61%) diff --git a/packages/compose/README.md b/packages/compose/README.md index d1ed64003eed20..016560af43f142 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -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. # **useConstrainedTabbing** diff --git a/packages/compose/src/hooks/use-async-list/index.js b/packages/compose/src/hooks/use-async-list/index.ts similarity index 61% rename from packages/compose/src/hooks/use-async-list/index.js rename to packages/compose/src/hooks/use-async-list/index.ts index 3189cd3a008684..97f410c09e6596 100644 --- a/packages/compose/src/hooks/use-async-list/index.js +++ b/packages/compose/src/hooks/use-async-list/index.ts @@ -1,3 +1,9 @@ +/** + * External dependencies + */ +// eslint-disable-next-line no-restricted-imports +import type { Reducer } from 'react'; + /** * WordPress dependencies */ @@ -7,11 +13,11 @@ 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++ ) { @@ -26,15 +32,22 @@ function getFirstItemsPresentInState( list, state ) { return firstItems; } +type ResetAction< T > = { type: 'reset'; list: T[] }; +type AppendAction< T > = { type: 'append'; item: T }; + /** * Reducer keeping track of a list of appended items. * - * @param {Array} state Current state - * @param {Object} action Action + * @template T + * @param state Current state + * @param action Action * - * @return {Array} update state. + * @return update state. */ -function listReducer( state, action ) { +function listReducer< T >( + state: T[], + action: ResetAction< T > | AppendAction< T > +): T[] { if ( action.type === 'reset' ) { return action.list; } @@ -50,11 +63,14 @@ function listReducer( state, action ) { * 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, dispatch ] = useReducer( + listReducer as Reducer< T[], ResetAction< T > | AppendAction< T > >, + [] as T[] + ); useEffect( () => { // On reset, we keep the first items that were previously rendered. @@ -64,7 +80,7 @@ function useAsyncList( list ) { list: firstItems, } ); const asyncQueue = createQueue(); - const append = ( index ) => () => { + const append = ( index: number ) => () => { if ( list.length <= index ) { return; } diff --git a/packages/compose/tsconfig.json b/packages/compose/tsconfig.json index 54091425924734..e9b29efe60bb68 100644 --- a/packages/compose/tsconfig.json +++ b/packages/compose/tsconfig.json @@ -8,6 +8,7 @@ "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/**/*" ] From ad945da7a9dcf1b57a7977fa47137c7ec4134107 Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Wed, 5 May 2021 14:09:15 -0700 Subject: [PATCH 2/3] Add missing type references --- packages/compose/tsconfig.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/compose/tsconfig.json b/packages/compose/tsconfig.json index e9b29efe60bb68..4b96b6ec4ae09e 100644 --- a/packages/compose/tsconfig.json +++ b/packages/compose/tsconfig.json @@ -2,8 +2,12 @@ "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/**/*", From 3ce36c41e12248db504c9e44ee68056b2e00977b Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Thu, 6 May 2021 06:06:01 -0700 Subject: [PATCH 3/3] Implement promosed simplification --- .../compose/src/hooks/use-async-list/index.ts | 48 ++----------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/packages/compose/src/hooks/use-async-list/index.ts b/packages/compose/src/hooks/use-async-list/index.ts index 97f410c09e6596..527142be2033f2 100644 --- a/packages/compose/src/hooks/use-async-list/index.ts +++ b/packages/compose/src/hooks/use-async-list/index.ts @@ -1,13 +1,7 @@ -/** - * External dependencies - */ -// eslint-disable-next-line no-restricted-imports -import type { Reducer } from 'react'; - /** * WordPress dependencies */ -import { useEffect, useReducer } from '@wordpress/element'; +import { useEffect, useState } from '@wordpress/element'; import { createQueue } from '@wordpress/priority-queue'; /** @@ -32,33 +26,6 @@ function getFirstItemsPresentInState< T >( list: T[], state: T[] ): T[] { return firstItems; } -type ResetAction< T > = { type: 'reset'; list: T[] }; -type AppendAction< T > = { type: 'append'; item: T }; - -/** - * Reducer keeping track of a list of appended items. - * - * @template T - * @param state Current state - * @param action Action - * - * @return update state. - */ -function listReducer< T >( - state: T[], - action: ResetAction< T > | AppendAction< T > -): T[] { - 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. @@ -67,24 +34,19 @@ function listReducer< T >( * @return Async array. */ function useAsyncList< T >( list: T[] ): T[] { - const [ current, dispatch ] = useReducer( - listReducer as Reducer< T[], ResetAction< T > | AppendAction< T > >, - [] as 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: 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 ) );