From 27a55381fbc903f1888c8535c7d9f51c72f71839 Mon Sep 17 00:00:00 2001 From: Hieu Vu Date: Fri, 4 Oct 2024 23:14:18 +0700 Subject: [PATCH 1/2] Homework --- src/components/Input/index.tsx | 98 ++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index 453c742..d0ebb32 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -2,6 +2,7 @@ import "./input.scss"; import { fetchData } from "../../utils/fetch-data"; import { debounce } from "../../utils/deboucne"; import Loader from "../Loader"; +import { useEffect, useState } from "react"; export interface InputProps { /** Placeholder of the input */ @@ -12,12 +13,101 @@ export interface InputProps { const Input = ({ placeholder, onSelectItem }: InputProps) => { // DO NOT remove this log - console.log('input re-render') + console.log("input re-render"); - // Your code start here - return + const [inputValue, setInputValue] = useState(""); + const [status, setStatus] = useState< + "initial" | "fetching" | "success" | "error" + >("initial"); + const [items, setItems] = useState([]); + const [errorMessage, setErrorMessage] = useState(""); + + useEffect(() => { + let isCurrent = true; + + const handleFetchData = async (value: string) => { + if (!value) { + setStatus("initial"); + setItems([]); + setErrorMessage(""); + return; + } + + setStatus("fetching"); + setErrorMessage(""); + + try { + const result = await fetchData(value); + if (isCurrent) { + setItems(result.length ? result : []); + setStatus("success"); + } + } catch (error) { + if (isCurrent) { + setStatus("error"); + setErrorMessage(error as string); + } + } + }; + + // Debounced version of handleFetchData + const debouncedFetchData = debounce(handleFetchData, 100); + + if (inputValue) { + debouncedFetchData(inputValue); + } + + return () => { + isCurrent = false; + }; + }, [inputValue]); + + // Handle input change + const handleInputChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + // Handle item click + const handleItemClick = (item: string) => { + onSelectItem(item); + }; + + return ( +
+ {/* Input */} + + + {/* Loader */} + {status === "fetching" && } + + {/* Error message */} + {status === "error" && errorMessage && ( +

{errorMessage}

+ )} + + {/* List of items */} + {status === "success" && ( +
    + {items.length ? ( + items.map((item, index) => ( +
  • handleItemClick(item)}> + {item} +
  • + )) + ) : ( +

    No results

    + )} +
+ )} +
+ ); // Your code end here }; export default Input; - From a005efea62e8f6b6a28b20ad35213e45922c8e6e Mon Sep 17 00:00:00 2001 From: Hieu Vu Date: Fri, 4 Oct 2024 23:40:15 +0700 Subject: [PATCH 2/2] test deploy --- src/components/Input/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index d0ebb32..881781e 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -50,7 +50,7 @@ const Input = ({ placeholder, onSelectItem }: InputProps) => { } }; - // Debounced version of handleFetchData + // Debounced version of handleFetchData test deploy const debouncedFetchData = debounce(handleFetchData, 100); if (inputValue) {