Move query param logic from SearchBar to SearchPage

Signed-off-by: Camila Belo <camilaibs@gmail.com>
Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Camila Belo
2021-05-25 14:36:58 +02:00
committed by Eric Peterson
parent c70139e732
commit db6fd04d73
2 changed files with 44 additions and 22 deletions
@@ -14,9 +14,8 @@
* limitations under the License.
*/
import React from 'react';
import React, { useState } from 'react';
import { useDebounce } from 'react-use';
import { useQueryParamState } from '@backstage/core';
import { Paper, InputBase, IconButton, makeStyles } from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
import ClearButton from '@material-ui/icons/Clear';
@@ -32,23 +31,26 @@ const useStyles = makeStyles(() => ({
},
}));
export const SearchBarNext = () => {
type Props = {
debounceTime?: number;
};
export const SearchBarNext = ({ debounceTime = 200 }: Props) => {
const classes = useStyles();
const { term, setTerm, setPageCursor } = useSearch();
const [, setQueryString] = useQueryParamState<string>('query');
const [value, setValue] = useState<string>(term);
useDebounce(
() => {
setQueryString(term);
setTerm(value);
},
200,
[term],
debounceTime,
[value],
);
const handleSearch = (event: React.ChangeEvent | React.FormEvent) => {
event.preventDefault();
setTerm((event.target as HTMLInputElement).value as string);
setValue((event.target as HTMLInputElement).value as string);
};
const handleClearSearchBar = () => {
@@ -57,22 +59,18 @@ export const SearchBarNext = () => {
};
return (
<Paper
component="form"
onSubmit={e => handleSearch(e)}
className={classes.root}
>
<Paper component="form" onSubmit={handleSearch} className={classes.root}>
<IconButton disabled type="submit" aria-label="search">
<SearchIcon />
</IconButton>
<InputBase
className={classes.input}
placeholder="Search in Backstage"
value={term}
onChange={e => handleSearch(e)}
value={value}
onChange={handleSearch}
inputProps={{ 'aria-label': 'search backstage' }}
/>
<IconButton aria-label="search" onClick={() => handleClearSearchBar()}>
<IconButton aria-label="search" onClick={handleClearSearchBar}>
<ClearButton />
</IconButton>
</Paper>
@@ -17,15 +17,38 @@
import React from 'react';
import qs from 'qs';
import { Outlet, useLocation } from 'react-router';
import { useQueryParamState } from '@backstage/core';
import { SearchContextProvider } from '../SearchContext';
import { SearchContextProvider, useSearch } from '../SearchContext';
import { JsonObject } from '@backstage/config';
export const UrlUpdater = () => {
const { term, types, pageCursor, filters } = useSearch();
const newParams = qs.stringify(
{
query: term,
types,
pageCursor,
filters,
},
{ arrayFormat: 'brackets' },
);
const newUrl = `${window.location.pathname}?${newParams}`;
// We directly manipulate window history here in order to not re-render
// infinitely (state => location => state => etc). The intention of this
// code is just to ensure the right query/filters are loaded when a user
// clicks the "back" button after clicking a result.
window.history.replaceState(null, document.title, newUrl);
return null;
};
export const SearchPageNext = () => {
const location = useLocation();
const [queryString] = useQueryParamState<string>('query');
const filters = (qs.parse(location.search.substring(1), { arrayLimit: 0 })
.filters || {}) as JsonObject;
const query = qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {};
const filters = (query.filters as JsonObject) || {};
const queryString = (query.query as string) || '';
const initialState = {
term: queryString || '',
types: [],
@@ -35,6 +58,7 @@ export const SearchPageNext = () => {
return (
<SearchContextProvider initialState={initialState}>
<UrlUpdater />
<Outlet />
</SearchContextProvider>
);