Hey is a decentralized and permissionless social media app built with Lens Protocol 🌿

refactor: memoize event handlers (#5842)

authored by yoginth.com and committed by

GitHub 2515a9b2 cb7c3e7d

+50 -32
+3 -2
apps/web/src/components/Shared/BackButton.tsx
··· 1 1 import { ArrowLeftIcon } from "@heroicons/react/24/outline"; 2 + import { useCallback } from "react"; 2 3 import { useNavigate, useNavigationType } from "react-router"; 3 4 4 5 interface BackButtonProps { ··· 9 10 const navigate = useNavigate(); 10 11 const navType = useNavigationType(); 11 12 12 - const handleBack = () => { 13 + const handleBack = useCallback(() => { 13 14 if (path) { 14 15 navigate(path); 15 16 } else if (navType === "POP") { ··· 17 18 } else { 18 19 navigate(-1); 19 20 } 20 - }; 21 + }, [navType, navigate, path]); 21 22 22 23 return ( 23 24 <button
+3 -3
apps/web/src/components/Shared/LoginButton.tsx
··· 1 1 import { STATIC_IMAGES_URL } from "@hey/data/constants"; 2 - import type { MouseEvent } from "react"; 2 + import { type MouseEvent, useCallback } from "react"; 3 3 import { Button } from "@/components/Shared/UI"; 4 4 import { useAuthModalStore } from "@/store/non-persisted/modal/useAuthModalStore"; 5 5 ··· 16 16 }: LoginButtonProps) => { 17 17 const { setShowAuthModal } = useAuthModalStore(); 18 18 19 - const handleClick = (event: MouseEvent<HTMLButtonElement>) => { 19 + const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => { 20 20 event.stopPropagation(); 21 21 return setShowAuthModal(true); 22 - }; 22 + }, []); 23 23 24 24 return ( 25 25 <Button
+7 -4
apps/web/src/components/Shared/Navbar/NavItems/ThemeSwitch.tsx
··· 1 1 import { MoonIcon, SunIcon } from "@heroicons/react/24/outline"; 2 + import { useCallback } from "react"; 2 3 import cn from "@/helpers/cn"; 3 4 import { useTheme } from "@/hooks/useTheme"; 4 5 ··· 9 10 10 11 const ThemeSwitch = ({ className = "", onClick }: ThemeSwitchProps) => { 11 12 const { toggleTheme, theme } = useTheme(); 13 + 14 + const handleClick = useCallback(() => { 15 + toggleTheme(); 16 + onClick?.(); 17 + }, [toggleTheme, onClick]); 12 18 13 19 return ( 14 20 <button ··· 16 22 "flex w-full items-center space-x-1.5 px-2 py-1.5 text-left text-gray-700 text-sm dark:text-gray-200", 17 23 className 18 24 )} 19 - onClick={() => { 20 - toggleTheme(); 21 - onClick?.(); 22 - }} 25 + onClick={handleClick} 23 26 type="button" 24 27 > 25 28 {theme === "light" ? (
+15 -8
apps/web/src/components/Shared/Navbar/index.tsx
··· 14 14 UserGroupIcon as UserGroupSolid 15 15 } from "@heroicons/react/24/solid"; 16 16 import { STATIC_IMAGES_URL } from "@hey/data/constants"; 17 - import type { MouseEvent, ReactNode } from "react"; 17 + import { type MouseEvent, type ReactNode, useCallback } from "react"; 18 18 import { Link, useLocation } from "react-router"; 19 19 import Pro from "@/components/Shared/Navbar/NavItems/Pro"; 20 20 import { Image, Tooltip } from "@/components/Shared/UI"; ··· 88 88 const { appIcon } = usePreferencesStore(); 89 89 const { setShowAuthModal } = useAuthModalStore(); 90 90 91 - const handleLogoClick = (e: MouseEvent<HTMLAnchorElement>) => { 92 - if (pathname === "/") { 93 - e.preventDefault(); 94 - window.scrollTo(0, 0); 95 - } 96 - }; 91 + const handleLogoClick = useCallback( 92 + (e: MouseEvent<HTMLAnchorElement>) => { 93 + if (pathname === "/") { 94 + e.preventDefault(); 95 + window.scrollTo(0, 0); 96 + } 97 + }, 98 + [pathname] 99 + ); 100 + 101 + const handleAuthClick = useCallback(() => { 102 + setShowAuthModal(true); 103 + }, []); 97 104 98 105 return ( 99 106 <aside className="sticky top-5 mt-5 hidden w-10 shrink-0 flex-col items-center gap-y-5 md:flex"> ··· 113 120 <SignedAccount /> 114 121 </> 115 122 ) : ( 116 - <button onClick={() => setShowAuthModal(true)} type="button"> 123 + <button onClick={handleAuthClick} type="button"> 117 124 <Tooltip content="Login"> 118 125 <UserCircleIcon className="size-6" /> 119 126 </Tooltip>
+22 -15
apps/web/src/components/Shared/Search/index.tsx
··· 9 9 } from "@hey/indexer"; 10 10 import { useClickAway, useDebounce } from "@uidotdev/usehooks"; 11 11 import type { ChangeEvent, MutableRefObject } from "react"; 12 - import { useEffect, useState } from "react"; 12 + import { useCallback, useEffect, useState } from "react"; 13 13 import { useLocation, useNavigate, useSearchParams } from "react-router"; 14 14 import SingleAccount from "@/components/Shared/Account/SingleAccount"; 15 15 import Loader from "@/components/Shared/Loader"; ··· 35 35 const [accounts, setAccounts] = useState<AccountFragment[]>([]); 36 36 const debouncedSearchText = useDebounce<string>(searchText, 500); 37 37 38 - const handleReset = () => { 38 + const handleReset = useCallback(() => { 39 39 setShowDropdown(false); 40 40 setAccounts([]); 41 - }; 41 + }, []); 42 42 43 43 const dropdownRef = useClickAway(() => { 44 44 handleReset(); ··· 46 46 47 47 const [searchAccounts, { loading }] = useAccountsLazyQuery(); 48 48 49 - const handleSearch = (evt: ChangeEvent<HTMLInputElement>) => { 49 + const handleSearch = useCallback((evt: ChangeEvent<HTMLInputElement>) => { 50 50 const keyword = evt.target.value; 51 51 setSearchText(keyword); 52 - }; 52 + }, []); 53 + 54 + const handleKeyDown = useCallback( 55 + (evt: ChangeEvent<HTMLFormElement>) => { 56 + evt.preventDefault(); 57 + if (pathname === "/search") { 58 + navigate(`/search?q=${encodeURIComponent(searchText)}&type=${type}`); 59 + } else { 60 + navigate(`/search?q=${encodeURIComponent(searchText)}&type=accounts`); 61 + } 62 + handleReset(); 63 + }, 64 + [pathname, navigate, searchText, type, handleReset] 65 + ); 53 66 54 - const handleKeyDown = (evt: ChangeEvent<HTMLFormElement>) => { 55 - evt.preventDefault(); 56 - if (pathname === "/search") { 57 - navigate(`/search?q=${encodeURIComponent(searchText)}&type=${type}`); 58 - } else { 59 - navigate(`/search?q=${encodeURIComponent(searchText)}&type=accounts`); 60 - } 61 - handleReset(); 62 - }; 67 + const handleShowDropdown = useCallback(() => { 68 + setShowDropdown(true); 69 + }, []); 63 70 64 71 useEffect(() => { 65 72 if (pathname !== "/search" && showDropdown && debouncedSearchText) { ··· 93 100 /> 94 101 } 95 102 onChange={handleSearch} 96 - onClick={() => setShowDropdown(true)} 103 + onClick={handleShowDropdown} 97 104 placeholder={placeholder} 98 105 type="text" 99 106 value={searchText}