SearchForm.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import React, {
  2. useCallback, useRef, useEffect, useMemo,
  3. } from 'react';
  4. import type { GetInputProps } from '../interfaces/downshift';
  5. type Props = {
  6. searchKeyword: string,
  7. onChange?: (text: string) => void,
  8. onSubmit?: () => void,
  9. getInputProps: GetInputProps,
  10. }
  11. export const SearchForm = (props: Props): JSX.Element => {
  12. const {
  13. searchKeyword, onChange, onSubmit, getInputProps,
  14. } = props;
  15. const inputRef = useRef<HTMLInputElement>(null);
  16. const changeSearchTextHandler = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
  17. onChange?.(e.target.value);
  18. }, [onChange]);
  19. const submitHandler = useCallback((e: React.FormEvent<HTMLFormElement>) => {
  20. e.preventDefault();
  21. const isEmptyKeyword = searchKeyword.trim().length === 0;
  22. if (isEmptyKeyword) {
  23. return;
  24. }
  25. onSubmit?.();
  26. }, [searchKeyword, onSubmit]);
  27. const inputOptions = useMemo(() => {
  28. return getInputProps({
  29. type: 'text',
  30. placeholder: 'Search...',
  31. className: 'form-control',
  32. ref: inputRef,
  33. value: searchKeyword,
  34. onChange: changeSearchTextHandler,
  35. });
  36. }, [getInputProps, searchKeyword, changeSearchTextHandler]);
  37. useEffect(() => {
  38. if (inputRef.current != null) {
  39. inputRef.current.focus();
  40. }
  41. });
  42. return (
  43. <form
  44. className="w-100 position-relative"
  45. onSubmit={submitHandler}
  46. data-testid="search-form"
  47. >
  48. <input {...inputOptions} />
  49. <button
  50. type="button"
  51. className="btn btn-neutral-secondary text-muted position-absolute bottom-0 end-0 w-auto h-100 border-0"
  52. onClick={() => { onChange?.('') }}
  53. >
  54. <span className="material-symbols-outlined p-0">cancel</span>
  55. </button>
  56. </form>
  57. );
  58. };