add useUpdateEffect and useFirstMountState | add endAdornment to search input

This commit is contained in:
Dawid Wysokiński 2020-11-11 18:14:58 +01:00
parent 4b4cd887ec
commit feffa53487
3 changed files with 58 additions and 5 deletions

View File

@ -1,7 +1,8 @@
import React from 'react';
import React, { useState, useRef } from 'react';
import { useQueryParams, StringParam, withDefault } from 'use-query-params';
import { useDebouncedCallback } from 'use-debounce';
import { useTranslation } from 'react-i18next';
import useUpdateEffect from '@libs/useUpdateEffect';
import { TWHELP, NAME } from '@config/app';
import * as NAMESPACES from '@config/namespaces';
@ -15,18 +16,24 @@ import {
Button,
Hidden,
Link,
IconButton,
} from '@material-ui/core';
import { Search as SearchIcon } from '@material-ui/icons';
import { Search as SearchIcon, Close as CloseIcon } from '@material-ui/icons';
import VersionSelector from '@common/VersionSelector/VersionSelector';
export default function Header() {
const input = useRef<HTMLInputElement | null>(null);
const [query, setQuery] = useQueryParams({
q: withDefault(StringParam, ''),
});
const [q, setQ] = useState(query.q);
const debouncedSetQuery = useDebouncedCallback(
value => setQuery({ q: value }),
1000
);
useUpdateEffect(() => {
debouncedSetQuery.callback(q);
}, [q]);
const { t } = useTranslation(NAMESPACES.INDEX_PAGE);
const classes = useStyles();
@ -39,18 +46,37 @@ export default function Header() {
fullWidth
variant="outlined"
placeholder={t<string>('header.search')}
defaultValue={query.q}
value={q}
inputRef={input}
size="small"
onChange={e => {
debouncedSetQuery.callback(e.target.value);
setQ(e.target.value);
}}
style={{ backgroundColor: 'rgba(0, 0, 0, 0.1)' }}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<InputAdornment
position="start"
onClick={() => {
if (input.current) {
input.current.focus();
}
}}
>
<SearchIcon />
</InputAdornment>
),
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
disabled={q === ''}
onClick={() => setQ('')}
>
<CloseIcon />
</IconButton>
</InputAdornment>
),
}}
/>
</div>

View File

@ -0,0 +1,13 @@
import { useRef } from 'react';
export default function useFirstMountState(): boolean {
const isFirst = useRef(true);
if (isFirst.current) {
isFirst.current = false;
return true;
}
return isFirst.current;
}

View File

@ -0,0 +1,14 @@
import { useEffect } from 'react';
import useFirstMountState from './useFirstMountState';
const useUpdateEffect: typeof useEffect = (effect, deps) => {
const isFirstMount = useFirstMountState();
useEffect(() => {
if (!isFirstMount) {
return effect();
}
}, deps);
};
export default useUpdateEffect;