From 0cf5774e16c7fd8fc444a056e3816e9836adddff Mon Sep 17 00:00:00 2001 From: rusconn Date: Wed, 24 May 2023 13:17:20 +0000 Subject: [PATCH] perf: speed up search --- README.md | 2 ++ app/layout.tsx | 21 ++++++++++++--------- app/search/page.tsx | 7 +++---- components/sidebar/search-bar.tsx | 12 ++++++++++-- contexts/search-text.tsx | 21 +++++++++++++++++++++ 5 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 contexts/search-text.tsx diff --git a/README.md b/README.md index 359b104..6ad59cc 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ A web clone of [DevToys](https://github.com/veler/DevToys) ## Known issues +- Tool search does not set query parameters + - [(Shallow routing) updating search params causes server code to rerun.](https://github.com/vercel/next.js/issues/49668) - [Editor may not resize to fit container size](https://github.com/suren-atoyan/monaco-react/issues/346) - CSS outlines messed up diff --git a/app/layout.tsx b/app/layout.tsx index a2ce5b5..630891a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,6 @@ import "@/styles/globals.css"; import { Metadata } from "next"; +import { SearchTextProvider } from "@/contexts/search-text"; import { siteConfig } from "@/config/site"; import { fontMono, fontSans } from "@/lib/fonts"; @@ -44,16 +45,18 @@ export default function RootLayout({ children }: RootLayoutProps) { )} > -
- -
- -
- {children} -
+ +
+ +
+ +
+ {children} +
+
-
- + + diff --git a/app/search/page.tsx b/app/search/page.tsx index d876eaa..db72b15 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useSearchParams } from "next/navigation"; +import { useSearchText } from "@/contexts/search-text"; import Fuse from "fuse.js"; import { homeTools } from "@/config/tools"; @@ -8,9 +8,8 @@ import { PageRootSection } from "@/components/page-root-section"; import { ToolCards } from "@/components/tool-cards"; export default function Page() { - const params = useSearchParams(); - - const q = params.get("q")?.trim() ?? ""; + // use search params in context + const q = useSearchText(); const fuse = new Fuse(homeTools, { keys: ["keywords"], threshold: 0.45 }); const keyWordsOptions = q.split(" ").map(word => ({ keywords: word })); diff --git a/components/sidebar/search-bar.tsx b/components/sidebar/search-bar.tsx index 7ce9062..3b0f060 100644 --- a/components/sidebar/search-bar.tsx +++ b/components/sidebar/search-bar.tsx @@ -1,7 +1,8 @@ "use client"; -import { useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { useRouter } from "next/navigation"; +import { useSetSearchText } from "@/contexts/search-text"; import { cn } from "@/lib/style"; import { Button, ButtonProps } from "@/components/ui/button"; @@ -12,10 +13,17 @@ export function SearchBar() { const router = useRouter(); const inputRef = useRef(null); const [text, setText] = useState(""); + const setSearchText = useSetSearchText(); + + // prefetch to speed up the first search + useEffect(() => router.prefetch("/search"), [router]); const search = () => { if (text.trim()) { - router.push(`/search?q=${text.trim()}`); + // next/navigation doesn't support shallow routing, use context instead of query params for speed + // https://github.com/vercel/next.js/issues/49668 + setSearchText(text.trim()); + router.push("/search"); } }; diff --git a/contexts/search-text.tsx b/contexts/search-text.tsx new file mode 100644 index 0000000..7e19de8 --- /dev/null +++ b/contexts/search-text.tsx @@ -0,0 +1,21 @@ +"use client"; + +import { PropsWithChildren, createContext, useContext, useState } from "react"; + +const SearchTextContext = createContext(""); +const SetSearchTextContext = createContext<(text: string) => void>(() => {}); + +export const useSearchText = () => useContext(SearchTextContext); +export const useSetSearchText = () => useContext(SetSearchTextContext); + +export const SearchTextProvider = ({ children }: PropsWithChildren) => { + const [searchText, setSearchText] = useState(""); + + return ( + + + {children} + + + ); +};