add useUpdateEffect and useFirstMountState | add endAdornment to search input
This commit is contained in:
parent
4b4cd887ec
commit
feffa53487
|
@ -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>
|
||||
|
|
13
src/libs/useFirstMountState.ts
Normal file
13
src/libs/useFirstMountState.ts
Normal 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;
|
||||
}
|
14
src/libs/useUpdateEffect.ts
Normal file
14
src/libs/useUpdateEffect.ts
Normal 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;
|
Reference in New Issue
Block a user