Add possibility to load other results on click

This commit is contained in:
rui hildt 2020-07-24 13:58:02 +02:00
parent 2b415b5189
commit a27a6281a0
4 changed files with 32 additions and 25 deletions

View File

@ -27,20 +27,20 @@ export default function App() {
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
const [getArtists, { data }] = useLazyQuery(QUERY_ARTISTS); const [getArtists, { data }] = useLazyQuery(QUERY_ARTISTS);
const [artists, setArtists] = useState<Artists>([]); const [artists, setArtists] = useState<Artists>([]);
const [suggestions, setSuggestions] = useState<string[] | undefined>(); const [suggestions, setSuggestions] = useState<string[]>([]);
const [selected, setSelected] = useState(false); const [selected, setSelected] = useState(false);
// Debounce the database query // Debounce the database query
// Based on: https://archive.is/wip/6JDqb // Based on: https://archive.is/wip/6JDqb
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (value: string) => {
setInputValue(e.target.value); setInputValue(value);
}; };
const updateQuery = () => { const updateQuery = () => {
getArtists({ variables: { byName: inputValue } }); getArtists({ variables: { byName: inputValue } });
}; };
const delayedQuery = useCallback(debounce(updateQuery, 500), [inputValue]); const delayedQuery = useCallback(debounce(updateQuery, 200), [inputValue]);
useEffect(() => { useEffect(() => {
delayedQuery(); delayedQuery();
@ -48,18 +48,14 @@ export default function App() {
return delayedQuery.cancel; return delayedQuery.cancel;
}, [inputValue, delayedQuery]); }, [inputValue, delayedQuery]);
const handleSelect = (suggestion: any) => { const handleSelect = (suggestion: string) => {
const selectedName: string = suggestion.suggestion;
let updatedArtists: Artists = []; let updatedArtists: Artists = [];
// Use map to create a copy of the array let suggestedArtists: Artists = data.queryArtists.slice(0, 5);
let suggestedArtists: Artists = data.queryArtists
.slice(0, 5)
.map((item: Artist) => item);
// Find the selected artist and move it to index 0 // Find the selected artist and move it to index 0
for (let i = 0; i < suggestedArtists!.length; i++) { for (let i = 0; i < suggestedArtists!.length; i++) {
if (suggestedArtists![i].name === selectedName) { if (suggestedArtists![i].name === suggestion) {
let selectedArtist: Artists = suggestedArtists?.splice(i, 1); let selectedArtist: Artists = suggestedArtists?.splice(i, 1);
let otherArtists: Artists = suggestedArtists; let otherArtists: Artists = suggestedArtists;
updatedArtists = [...selectedArtist, ...otherArtists]; updatedArtists = [...selectedArtist, ...otherArtists];
@ -71,13 +67,22 @@ export default function App() {
setSelected(true); setSelected(true);
}; };
const handleClick = () => { const handleClick = (name: string) => {
console.log('click') let updatedArtists: Artists = [];
for (let i = 0; i < artists.length; i++) {
if (artists[i].name === name) {
let selectedArtist: Artists = artists.splice(i, 1);
let otherArtists: Artists = artists;
updatedArtists = [...selectedArtist, ...otherArtists];
break;
}
} }
setArtists(updatedArtists);
};
useEffect(() => { useEffect(() => {
// TODO optimize re-rendering, probably by using onCompleted instead of this useEffect
// See https://github.com/apollographql/apollo-client/issues/5268#issuecomment-596950174
if (data && data.queryArtists !== []) { if (data && data.queryArtists !== []) {
// Limit artists to 5 // Limit artists to 5
const updatedArtists = data.queryArtists.slice(0, 5); const updatedArtists = data.queryArtists.slice(0, 5);
@ -101,7 +106,9 @@ export default function App() {
suggestions={suggestions} suggestions={suggestions}
handleSelect={handleSelect} handleSelect={handleSelect}
/> />
{selected && <Results artists={artists} handleClick={handleClick}/>} {selected && (
<Results artists={artists} handleClick={handleClick} />
)}
</Grommet> </Grommet>
); );
} }

View File

@ -8,7 +8,7 @@ export const Other = ({
}: { }: {
image: string; image: string;
name: string; name: string;
handleClick: ((...args: any[]) => any) & ((event: MouseEvent) => void); handleClick: (name: string) => void;
}) => { }) => {
return ( return (
<Box <Box
@ -16,7 +16,7 @@ export const Other = ({
overflow='hidden' overflow='hidden'
align='center' align='center'
pad='small' pad='small'
onClick={handleClick} onClick={() => handleClick(name)}
> >
<Heading <Heading
level='4' level='4'

View File

@ -10,7 +10,7 @@ export const Results = ({
handleClick, handleClick,
}: { }: {
artists: Artists; artists: Artists;
handleClick: ((...args: any[]) => any) & ((event: MouseEvent) => void); handleClick: (name: string) => void;
}) => { }) => {
const { const {
name: selectedName, name: selectedName,

View File

@ -9,9 +9,9 @@ export const Search = ({
handleSelect, handleSelect,
}: { }: {
inputValue: string; inputValue: string;
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void; handleChange: (value: string) => void;
suggestions: string[] | undefined; suggestions: string[];
handleSelect: (x: { target: HTMLElement | null; suggestion: any }) => void; handleSelect: (suggestion: string) => void;
}) => ( }) => (
<Box <Box
as='section' as='section'
@ -21,8 +21,8 @@ export const Search = ({
> >
<TextInput <TextInput
value={inputValue} value={inputValue}
onChange={handleChange} onChange={e => handleChange(e.target.value)}
onSelect={handleSelect} onSelect={(target) => handleSelect(target.suggestion)}
placeholder='Type an artist name' placeholder='Type an artist name'
icon={<FormSearch color='plain' />} icon={<FormSearch color='plain' />}
dropHeight='large' dropHeight='large'