'Create custom Search bar in react to search through firebase document

I want to create a custom search bar to query my firestore document retrieve collection based on user input.

I know there are better options to do this like

Algolia, Typesense etc

But I have issues with firebase upgrading my account, and I have contacted the firebase team.

DrinkSearch.tsx

const DrinkSearch: React.FC = () => {
  const [searchTerm, setSearchTerm] = useState("");
  const [drinkSnap, setDrinkSnap] = useState<
    QueryDocumentSnapshot<DocumentData>[]
  >([]);
  const [isLoading, setIsLoading] = useState(false);

  const drinkRef = collection(firebaseFirestore, "products");

  const drinkQuery = query(drinkRef, where("drinkName", "==", searchTerm));
  const snapshots = getDocs(drinkQuery);
  let docsIsEmpty!: boolean;

  const getProductOnChange = () => {
    setIsLoading(true);
    snapshots
      .then((docsSnapshot) => {
        setIsLoading(false);
        setDrinkSnap(docsSnapshot?.docs);
        docsIsEmpty = docsSnapshot?.empty;
        console.log(docsSnapshot?.docs);
      })
      .catch((error: FirestoreError) => {
        setIsLoading(false);
        console.log(error.message);
      });
  };

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(e.currentTarget.value);

    getProductOnChange();
  };

  useEffect(() => {
    console.log(searchTerm);
  }, [searchTerm]);

  return (
    <Box>
      <InputGroup size="lg">
        <InputLeftElement pointerEvents="none">
          <RiSearch2Line color="#CBD5E0" size="20px" />
        </InputLeftElement>
        <Input
          onChange={handleChange}
          type="text"
          _focus={{
            boxShadow: shadowSm,
          }}
          fontSize="14px"
          placeholder="Search for drinks"
        />
      </InputGroup>
      <Box
        padding={5}
        bgColor="white"
        height="40px"
        borderBottomRadius={"8px"}
        border={"1px solid #EDF2F7"}
      >
        {docsIsEmpty && <Text>Drink not found.</Text>}
        {isLoading && (
          <Flex height="100%">
            <Spinner size={"sm"} colorScheme={"primary.500"} />
          </Flex>
        )}
        {drinkSnap &&
          drinkSnap?.map((drinkSnap) => {
            const drinks = drinkSnap?.data();
            return (
              <HStack
                cursor={"pointer"}
                justify={"space-between"}
                padding={"5px"}
                _hover={{
                  bgColor: "#EDF2F7",
                }}
                key={drinkSnap?.id}
              >
                <Text fontWeight={"semibold"}>{drinks?.drinkName}</Text>
                <Badge fontSize={"12px"}>{drinks?.category}</Badge>
              </HStack>
            );
          })}
      </Box>
    </Box>
  );
};

export default DrinkSearch;

Result: When I start typing for example black label is the name of a drink, nothing happens i.e the [] is empty. When I remove 'l'. it remains black labe, it returns the array with the collection.

What i want: On typing, return all collections that match what is typed.

Thanks in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source