feat: Adds support for clearing the Select cache (#20397)

* feat: Adds support for clearing the Select cache

* Fixes lint errors
This commit is contained in:
Michael S. Molina 2022-06-21 15:13:37 -03:00 committed by GitHub
parent 44c5e2879b
commit ca526e63c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 7 deletions

View File

@ -16,9 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { ReactNode, useState, useCallback } from 'react';
import React, { ReactNode, useState, useCallback, useRef } from 'react';
import Button from 'src/components/Button';
import ControlHeader from 'src/explore/components/ControlHeader';
import Select, { SelectProps, OptionsTypePage, OptionsType } from './Select';
import Select, {
SelectProps,
OptionsTypePage,
OptionsType,
SelectRef,
} from './Select';
export default {
title: 'Select',
@ -387,6 +393,7 @@ export const AsyncSelect = ({
responseTime: number;
}) => {
const [requests, setRequests] = useState<ReactNode[]>([]);
const ref = useRef<SelectRef>(null);
const getResults = (username?: string) => {
let results: { label: string; value: string }[] = [];
@ -458,6 +465,7 @@ export const AsyncSelect = ({
>
<Select
{...rest}
ref={ref}
fetchOnlyOnSearch={fetchOnlyOnSearch}
options={withError ? fetchUserListError : fetchUserListPage}
placeholder={fetchOnlyOnSearch ? 'Type anything' : 'Select...'}
@ -484,6 +492,19 @@ export const AsyncSelect = ({
<p key={`request-${index}`}>{request}</p>
))}
</div>
<Button
style={{
position: 'absolute',
top: 452,
left: DEFAULT_WIDTH + 580,
}}
onClick={() => {
ref.current?.clearCache();
setRequests([]);
}}
>
Clear cache
</Button>
</>
);
};

View File

@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import React, { RefObject } from 'react';
import { render, screen, waitFor, within } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import { Select } from 'src/components';
import { SelectRef } from './Select';
const ARIA_LABEL = 'Test';
const NEW_OPTION = 'Kyle';
@ -813,6 +814,21 @@ test('async - fires a new request if all values have not been fetched', async ()
expect(mock).toHaveBeenCalledTimes(2);
});
test('async - requests the options again after clearing the cache', async () => {
const ref: RefObject<SelectRef> = { current: null };
const mock = jest.fn(loadOptions);
const pageSize = OPTIONS.length;
render(
<Select {...defaultProps} options={mock} pageSize={pageSize} ref={ref} />,
);
await open();
expect(mock).toHaveBeenCalledTimes(1);
ref.current?.clearCache();
await type('{esc}');
await open();
expect(mock).toHaveBeenCalledTimes(2);
});
/*
TODO: Add tests that require scroll interaction. Needs further investigation.
- Fetches more data when scrolling and more data is available

View File

@ -27,6 +27,7 @@ import React, {
useState,
useRef,
useCallback,
useImperativeHandle,
} from 'react';
import { ensureIsArray, styled, t } from '@superset-ui/core';
import AntdSelect, {
@ -81,6 +82,8 @@ export type OptionsPagePromise = (
pageSize: number,
) => Promise<OptionsTypePage>;
export type SelectRef = HTMLInputElement & { clearCache: () => void };
export interface SelectProps extends PickedSelectProps {
/**
* It enables the user to create new options.
@ -315,7 +318,7 @@ const Select = (
value,
...props
}: SelectProps,
ref: RefObject<HTMLInputElement>,
ref: RefObject<SelectRef>,
) => {
const isAsync = typeof options === 'function';
const isSingleMode = mode === 'single';
@ -678,6 +681,17 @@ const Select = (
}
}, [isLoading, loading]);
const clearCache = () => fetchedQueries.current.clear();
useImperativeHandle(
ref,
() => ({
...(ref.current as HTMLInputElement),
clearCache,
}),
[ref],
);
return (
<StyledContainer>
{header}

View File

@ -23,6 +23,7 @@ import {
QueryFormData,
} from '@superset-ui/core';
import { RefObject } from 'react';
import { SelectRef } from 'src/components/Select/Select';
import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
interface PluginFilterGroupByCustomizeProps {
@ -40,7 +41,7 @@ export type PluginFilterGroupByProps = PluginFilterStylesProps & {
data: DataRecord[];
filterState: FilterState;
formData: PluginFilterGroupByQueryFormData;
inputRef: RefObject<HTMLInputElement>;
inputRef: RefObject<SelectRef>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterGroupByCustomizeProps = {

View File

@ -23,6 +23,7 @@ import {
QueryFormData,
} from '@superset-ui/core';
import { RefObject } from 'react';
import { SelectRef } from 'src/components/Select/Select';
import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
interface PluginFilterTimeColumnCustomizeProps {
@ -39,7 +40,7 @@ export type PluginFilterTimeColumnProps = PluginFilterStylesProps & {
data: DataRecord[];
filterState: FilterState;
formData: PluginFilterTimeColumnQueryFormData;
inputRef: RefObject<HTMLInputElement>;
inputRef: RefObject<SelectRef>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterTimeColumnCustomizeProps = {

View File

@ -18,6 +18,7 @@
*/
import { FilterState, QueryFormData, DataRecord } from '@superset-ui/core';
import { RefObject } from 'react';
import { SelectRef } from 'src/components/Select/Select';
import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
interface PluginFilterTimeGrainCustomizeProps {
@ -33,7 +34,7 @@ export type PluginFilterTimeGrainProps = PluginFilterStylesProps & {
data: DataRecord[];
filterState: FilterState;
formData: PluginFilterTimeGrainQueryFormData;
inputRef: RefObject<HTMLInputElement>;
inputRef: RefObject<SelectRef>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterTimeGrainCustomizeProps = {