Guest User

Untitled

a guest
May 24th, 2024
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.26 KB | None | 0 0
  1. import { createFileRoute, notFound, useNavigate } from "@tanstack/react-router"
  2. import { useContext } from "react"
  3. import { PetCard } from "../../components/PetCard"
  4. import { Animal } from "../../types"
  5. import { IsDropdownClickedContext } from "../../context/IsDropdownClicked"
  6. import { useQuery } from "@tanstack/react-query"
  7. import { useDebounce } from "../../utils/useDebounce"
  8.  
  9. type PetSearch = {
  10. query: string
  11. }
  12.  
  13. export const Route = createFileRoute("/pets/$petCategory")({
  14. component: PetCategory,
  15. loader: async ({ params }) => {
  16. if (!["dogs", "cats", "birds"].includes(params.petCategory)) {
  17. throw notFound()
  18. }
  19. },
  20. validateSearch: (search: Record<string, unknown>): PetSearch => {
  21. return { query: search.query as string }
  22. },
  23. })
  24.  
  25. export default function PetCategory() {
  26. const { petCategory } = Route.useParams()
  27. const { isClicked, isHidden } = useContext(IsDropdownClickedContext)
  28. const { query } = Route.useSearch<PetSearch>()
  29. const debouncedSearch = useDebounce(query)
  30. const navigate = useNavigate({ from: Route.fullPath })
  31.  
  32. const {
  33. data: animalArray,
  34. isLoading,
  35. error,
  36. } = useQuery({
  37. queryFn: async () => {
  38. console.log(debouncedSearch)
  39. const queryToFetch = debouncedSearch ? `?search=${debouncedSearch}` : ""
  40. const res = await fetch(
  41. `https://freetestapi.com/api/v1/${petCategory}${queryToFetch}`
  42. )
  43.  
  44. const data = await res.json()
  45. return data
  46. },
  47. queryKey: ["pets", debouncedSearch],
  48. })
  49.  
  50. if (isLoading) {
  51. return (
  52. <div className="text-4xl text-white text-center my-10 uppercase">
  53. Loading...
  54. </div>
  55. )
  56. }
  57. if (error) {
  58. return (
  59. <div className="text-4xl text-white text-center my-10 uppercase">
  60. {error.message}
  61. </div>
  62. )
  63. }
  64. if(debouncedSearch === query){
  65. return (
  66. <div>
  67. <h1 className="text-4xl text-white text-center my-10 uppercase">
  68. {petCategory}
  69. </h1>
  70. <input
  71. type="text"
  72. className={`${
  73. isClicked && !isHidden ? "top-44" : !isHidden ? "top-20" : "top-4"
  74. } left-0 right-0 sticky mx-auto p-3 block mb-8 w-3/4 md:w-2/4 rounded-md `}
  75. placeholder={`Search through the ${petCategory} list`}
  76. onChange={(e) => {
  77. navigate({ search: (prev) => ({ ...prev, query: e.target.value }) })
  78. }}
  79. value={query}
  80. />
  81. <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 gap-y-8 w-3/4 mx-auto">
  82. {animalArray!.map((animal: Animal, index: number) => (
  83. <PetCard
  84. key={animal.id}
  85. index={index}
  86. animal={animal}
  87. animalType={petCategory!}
  88. />
  89. ))}
  90. </div>
  91. </div>
  92. )
  93. }
  94. }
  95.  
  96.  
  97.  
  98. /// useDebounceHook
  99.  
  100. import { useEffect, useState } from "react"
  101.  
  102. export const useDebounce = (search: string, delay: number = 500) => {
  103. const [debouncedSearch, setDebouncedSearch] = useState<string>("")
  104.  
  105. useEffect(() => {
  106. const delaySearch = setTimeout(() => {
  107. setDebouncedSearch(search)
  108. }, delay)
  109.  
  110. return () => clearTimeout(delaySearch)
  111. }, [search])
  112.  
  113. return debouncedSearch
  114. }
  115.  
Advertisement
Add Comment
Please, Sign In to add comment