Improve response filter UX

This commit is contained in:
Gregory Schier
2024-01-15 15:19:29 -08:00
parent 1d207d5fbd
commit 49ed756479
2 changed files with 12 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
import { useState } from 'react'; import { useCallback } from 'react';
import { useDebouncedSetState } from '../../hooks/useDebouncedSetState'; import { useDebouncedSetState } from '../../hooks/useDebouncedSetState';
import { useFilterResponse } from '../../hooks/useFilterResponse'; import { useFilterResponse } from '../../hooks/useFilterResponse';
import { useResponseBodyText } from '../../hooks/useResponseBodyText'; import { useResponseBodyText } from '../../hooks/useResponseBodyText';
@@ -18,7 +18,7 @@ interface Props {
export function TextViewer({ response, pretty }: Props) { export function TextViewer({ response, pretty }: Props) {
const [isSearching, toggleIsSearching] = useToggle(); const [isSearching, toggleIsSearching] = useToggle();
const [filterText, setFilterText] = useDebouncedSetState<string>('', 500); const [filterText, setDebouncedFilterText, setFilterText] = useDebouncedSetState<string>('', 400);
const contentType = useResponseContentType(response); const contentType = useResponseContentType(response);
const rawBody = useResponseBodyText(response) ?? ''; const rawBody = useResponseBodyText(response) ?? '';
@@ -26,6 +26,10 @@ export function TextViewer({ response, pretty }: Props) {
const filteredResponse = useFilterResponse({ filter: filterText, responseId: response.id }); const filteredResponse = useFilterResponse({ filter: filterText, responseId: response.id });
const body = filteredResponse ?? formattedBody; const body = filteredResponse ?? formattedBody;
const clearSearch = useCallback(() => {
toggleIsSearching();
setFilterText('');
}, [setFilterText, toggleIsSearching]);
const actions = contentType?.startsWith('application/json') && ( const actions = contentType?.startsWith('application/json') && (
<HStack className="w-full" justifyContent="end" space={1}> <HStack className="w-full" justifyContent="end" space={1}>
@@ -39,14 +43,15 @@ export function TextViewer({ response, pretty }: Props) {
label="Filter with JSONPath" label="Filter with JSONPath"
name="filter" name="filter"
defaultValue={filterText} defaultValue={filterText}
onChange={setFilterText} onKeyDown={(e) => e.key === 'Escape' && clearSearch()}
onChange={setDebouncedFilterText}
/> />
)} )}
<IconButton <IconButton
size="sm" size="sm"
icon={isSearching ? 'x' : 'magnifyingGlass'} icon={isSearching ? 'x' : 'magnifyingGlass'}
title="Filter response" title={isSearching ? 'Close filter' : 'Filter response'}
onClick={toggleIsSearching} onClick={clearSearch}
/> />
</HStack> </HStack>
); );

View File

@@ -5,8 +5,8 @@ import { debounce } from '../lib/debounce';
export function useDebouncedSetState<T>( export function useDebouncedSetState<T>(
defaultValue: T, defaultValue: T,
delay?: number, delay?: number,
): [T, Dispatch<SetStateAction<T>>] { ): [T, Dispatch<SetStateAction<T>>, Dispatch<SetStateAction<T>>] {
const [state, setState] = useState<T>(defaultValue); const [state, setState] = useState<T>(defaultValue);
const debouncedSetState = useMemo(() => debounce(setState, delay), [delay]); const debouncedSetState = useMemo(() => debounce(setState, delay), [delay]);
return [state, debouncedSetState]; return [state, debouncedSetState, setState];
} }