|
1 | 1 | import { Input, InputProps, makeStyles, mergeClasses } from '@fluentui/react-components';
|
2 | 2 | import { DismissRegular, SearchRegular } from "@fluentui/react-icons";
|
3 |
| -import { debounce, isNullOrEmptyString } from '@kwiz/common'; |
4 |
| -import React, { useRef } from 'react'; |
| 3 | +import { debounce, isNullOrEmptyString, isNullOrUndefined } from '@kwiz/common'; |
| 4 | +import React, { useEffect, useRef } from 'react'; |
5 | 5 | import { GetLogger } from '../_modules/config';
|
| 6 | +import { useEffectOnlyOnMount, useStateEX } from '../helpers'; |
6 | 7 | import { mixins } from '../styles/styles';
|
7 | 8 | const logger = GetLogger("Search");
|
8 | 9 |
|
@@ -36,26 +37,35 @@ export const Search: React.FunctionComponent<React.PropsWithChildren<IProps>> =
|
36 | 37 | React.useEffect(() => { refonChangeDeferred.current = props.onChangeDeferred; }, [props.onChangeDeferred]);
|
37 | 38 |
|
38 | 39 | //cannot call debounce every render, since it won't be the same debounced instance...
|
39 |
| - var notifyParent = React.useMemo(() => debounce(v => { |
| 40 | + var notifyParent = React.useCallback(debounce(v => { |
40 | 41 | logger.log(`Set: ${v}`);
|
41 | 42 | //Call the latest ref - we don't want to call an old version of this function
|
42 | 43 | refonChangeDeferred.current?.(v);
|
43 | 44 | }, delay * 1000), [delay]);
|
44 | 45 |
|
45 |
| - const currentValue = props.value || ""; |
| 46 | + const [currentValue, setCurrentValue] = useStateEX(props.value || props.defaultValue || "", { skipUpdateIfSame: true }); |
| 47 | + useEffect(() => { |
| 48 | + if (!isNullOrUndefined(props.value)) |
| 49 | + setCurrentValue(props.value); |
| 50 | + }, [props.value]); |
| 51 | + |
| 52 | + var changeValue = React.useCallback((newValue: string) => { |
| 53 | + newValue = newValue || "";//no null or undefined here |
| 54 | + setCurrentValue(newValue);//keep our state updated in sync |
| 55 | + props.onChange?.(newValue);//if parent is using search as managed control, keep it up to date in sync |
| 56 | + notifyParent(newValue);//trigger a search async |
| 57 | + }, useEffectOnlyOnMount); |
46 | 58 |
|
47 | 59 | return (
|
48 |
| - <Input {...props} value={currentValue} onChange={(e, data) => { |
49 |
| - props.onChange?.(data.value); |
50 |
| - notifyParent(data.value); |
| 60 | + <Input {...props} autoFocus defaultValue={undefined} value={currentValue} onChange={(e, data) => { |
| 61 | + changeValue(data.value); |
51 | 62 | }}
|
52 | 63 | className={mergeClasses(cssNames.root, props.main && cssNames.main)}
|
53 | 64 | contentBefore={!isNullOrEmptyString(currentValue) ? undefined : <SearchRegular className={cssNames.searchIcon} />}
|
54 | 65 | contentAfter={isNullOrEmptyString(currentValue)
|
55 | 66 | ? undefined
|
56 | 67 | : <DismissRegular className={cssNames.clickable} onClick={() => {
|
57 |
| - props.onChange?.(""); |
58 |
| - notifyParent(""); |
| 68 | + changeValue(""); |
59 | 69 | }} />
|
60 | 70 | } />
|
61 | 71 | );
|
|
0 commit comments