{"id":25490,"date":"2026-06-17T23:46:20","date_gmt":"2026-06-17T23:46:20","guid":{"rendered":"https:\/\/umang.pk\/2026\/06\/17\/react-%d9%85%db%8c%da%ba-%db%8c%d9%88%d8%b2-%da%a9%d8%a7%d9%84-%d8%a8%db%8c%da%a9-%d8%a7%d9%88%d8%b1-%db%8c%d9%88%d8%b2-%d9%85%db%8c%d9%85%d9%88-%da%a9%db%92-%d8%ba%d9%84%d8%b7-%d8%a7%d8%b3%d8%aa\/"},"modified":"2026-06-17T23:46:22","modified_gmt":"2026-06-17T23:46:22","slug":"react-%d9%85%db%8c%da%ba-%db%8c%d9%88%d8%b2-%da%a9%d8%a7%d9%84-%d8%a8%db%8c%da%a9-%d8%a7%d9%88%d8%b1-%db%8c%d9%88%d8%b2-%d9%85%db%8c%d9%85%d9%88-%da%a9%db%92-%d8%ba%d9%84%d8%b7-%d8%a7%d8%b3%d8%aa","status":"publish","type":"post","link":"https:\/\/umang.pk\/en_us\/2026\/06\/17\/react-%d9%85%db%8c%da%ba-%db%8c%d9%88%d8%b2-%da%a9%d8%a7%d9%84-%d8%a8%db%8c%da%a9-%d8%a7%d9%88%d8%b1-%db%8c%d9%88%d8%b2-%d9%85%db%8c%d9%85%d9%88-%da%a9%db%92-%d8%ba%d9%84%d8%b7-%d8%a7%d8%b3%d8%aa\/","title":{"rendered":"React \u0645\u06cc\u06ba \u06cc\u0648\u0632 \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u0627\u0648\u0631 \u06cc\u0648\u0632 \u0645\u06cc\u0645\u0648 \u06a9\u06d2 \u063a\u0644\u0637 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u0628\u0686\u06cc\u06ba\u06d4"},"content":{"rendered":"\n<div id=\"\">\n<p>\u0627\u06af\u0631 \u0622\u067e \u0646\u06d2 React \u0627\u06cc\u06a9\u0648 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u06a9\u0627\u0641\u06cc \u0648\u0642\u062a \u06af\u0632\u0627\u0631\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0646\u06d2 \u0634\u0627\u06cc\u062f \u06a9\u0648\u0688 \u0628\u06cc\u0633\u0632 \u062f\u06cc\u06a9\u06be\u06d2 \u06c1\u0648\u06ba \u06af\u06d2 \u062c\u06c1\u0627\u06ba \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0627\u0633 \u0637\u0631\u062d \u0644\u067e\u06cc\u0679 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: <code>useCallback<\/code> \u062d\u0633\u0627\u0628\u06cc \u0642\u062f\u0631 \u0627\u0633 \u0637\u0631\u062d \u0644\u067e\u06cc\u0679\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2: <code>useMemo<\/code>.<\/p>\n<p>\u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 &quot;\u0646\u0648\u0679 \u0644\u06cc\u0646\u06d2 \u0633\u06d2 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u0628\u06c1\u062a\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4&#8221; \u062a\u0627\u06c1\u0645\u060c \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0645\u06cc\u06ba \u06cc\u06c1 \u0628\u06c1\u062a\u0631 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u0627 \u0628\u0627\u0639\u062b \u0646\u06c1\u06cc\u06ba \u0628\u0646\u062a\u0627 \u0627\u0648\u0631 \u0627\u06a9\u062b\u0631 \u0627\u06cc\u0633\u0627 \u06a9\u0648\u0688 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u0688\u06cc\u0628\u06af \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0622\u0631\u0679\u06cc\u06a9\u0644 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0633\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u06a9\u0633 \u0637\u0631\u062d \u0627\u067e\u0646\u06d2 \u06a9\u0648\u0688 \u06a9\u0648 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u0628\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06be\u0627\u0646\u0686\u06c1 \u0628\u0646\u0627\u0646\u0627 \u06c1\u06d2\u06d4 <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code>.<\/p>\n<h2 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h2>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u06a9\u0648 \u067e\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0622\u067e \u06a9\u0648 React \u06c1\u06a9\u0633 \u0627\u0648\u0631 \u0627\u062c\u0632\u0627\u0621 \u0633\u06d2 \u0648\u0627\u0642\u0641 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0648\u0627\u0642\u0641 <code>useState<\/code>\u060c <code>useEffect<\/code>\u0627\u0648\u0631 <code>useRef<\/code> \u0641\u0631\u0636 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 \u0631\u06cc\u0641\u0631\u06cc\u0634\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u0641\u062a \u06a9\u0648\u0688 \u06a9\u06cc\u0645\u067e \u0645\u0636\u0627\u0645\u06cc\u0646 \u067e\u0691\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code>:<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-what-usecallback-and-usememo-do\">\u06a9\u06cc\u0627 <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code> \u06a9\u0631\u0648<\/h2>\n<p>\u0627\u0633 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u06c1 \u06c1\u0645 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0637\u0631\u0641 \u0628\u0691\u06be\u06cc\u06ba \u06a9\u06c1 \u06a9\u0633 \u0637\u0631\u062d \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u0628\u0686\u0646\u0627 \u06c1\u06d2\u060c \u0622\u0626\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u0631\u0633\u0631\u06cc \u0646\u0638\u0631 \u0688\u0627\u0644\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u06c1\u06a9\u0633 \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-usememo\">\u0646\u0648\u0679 \u067e\u0631<\/h3>\n<p><code>useMemo<\/code>    \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u06cc\u0645\u062a \u06a9\u0648 \u06a9\u06cc\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 \u0641\u0631\u0636 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u0627\u062c\u0632\u0627\u0621 \u0645\u06cc\u06ba \u0627\u0634\u06cc\u0627\u0621 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0634\u062f\u06c1 \u0641\u06c1\u0631\u0633\u062a \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">interface Item {\n  name: string;\n  createdAt: string;\n}\n\nfunction App() {\n  \/\/ == some other states ==\n  \/\/ == some other states ==\n  const [items, setItems] = useState<item>([]);\n\n  const sortedItems = [...items].sort(\n    (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),\n  );\n\n  return (\n    <>\n      <ul>\n        {sortedItems.map((i) => (\n          <li key=\"{i.name}\">{i.name}<\/li>\n        ))}\n      <\/ul>\n    >\n  );\n}\n<\/item><\/code><\/pre>\n<p>React recalculates. <code>sortedItems<\/code> \u06c1\u0631 \u0628\u0627\u0631 <code>App<\/code> \u062c\u0632\u0648 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2: <code>sortedItems<\/code> \u062c\u0628 \u0628\u06be\u06cc \u0631\u06cc\u0627\u0633\u062a \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u0633 \u06a9\u0627 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>App<\/code> \u0639\u0646\u0635\u0631<\/p>\n<p>React \u0688\u0648\u06cc\u0644\u067e\u0631\u0632 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0627\u06a9\u062b\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>useMemo<\/code> \u06a9\u06cc\u0634\u06d2 \u06a9\u06cc \u0642\u062f\u0631\u06cc\u06ba \u0627\u0633 \u0637\u0631\u062d \u06c1\u06cc\u06ba:<\/p>\n<p>\u0627\u0633\u06d2 \u0644\u067e\u06cc\u0679 \u062f\u0648 <code>useMemo<\/code> \u06af\u0627\u0631\u0646\u0679\u06cc <code>sortedItems<\/code> \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u0634\u0645\u0627\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062c\u0628: <code>items<\/code> \u06cc\u06c1\u0627\u06ba \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0622\u062a\u06cc \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">const sortedItems = useMemo(() => {\n  return [...items].sort(\n    (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(),\n  );\n}, [items]);\n<\/code><\/pre>\n<h3 id=\"heading-usecallback\">\u06a9\u0627\u0644 \u0628\u06cc\u06a9\u0633 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p><code>useCallback<\/code>    \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u06c1\u06cc \u06a9\u06cc\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 \u062c\u0628 \u0628\u06be\u06cc \u062c\u0632\u0648 \u06a9\u06cc \u06a9\u0686\u06be \u062d\u0627\u0644\u062a \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u0646\u06cc\u0686\u06d2 \u06a9\u0627 \u0641\u0646\u06a9\u0634\u0646 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<pre><code class=\"language-typescript\">function App() {\n  \/\/ == some other states ==\n  \/\/ == some other states ==\n  const [userId, setUserId] = useState(0);\n\n  const verifyUser = async () => {\n    \/\/ update a state to show loading\n    console.log(\"__ Do something with user id __\", userId);\n    \/\/ update a state to remove loading\n  };\n\n  return (\n    <>\n      <button onclick=\"{verifyUser}\">Verify<\/button>\n    >\n  );\n}\n<\/code><\/pre>\n<p>\u0627\u0633\u06d2 \u0644\u067e\u06cc\u0679 \u062f\u0648 <code>useCallback<\/code> \u0627\u06cc\u06a9 \u06c1\u06cc \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u0631\u06a9\u06be\u06cc\u06ba\u06d4 <code>userId<\/code> \u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f\u06c1:<\/p>\n<pre><code class=\"language-typescript\">function App() {\n  \/\/ == some other states ==\n  \/\/ == some other states ==\n  const [userId, setUserId] = useState(0);\n\n  const verifyUser = useCallback(async () => {\n    \/\/ update a state to show loading\n    console.log(\"__ Do something with user id __\", userId);\n    \/\/ update a state to remove loading\n  }, [userId]);\n\n  return (\n    <>\n      <button onclick=\"{verifyUser}\">Verify<\/button>\n    >\n  );\n}\n<\/code><\/pre>\n<h2 id=\"heading-problem-with-memoization\">\u0645\u06cc\u0645\u0648 \u0645\u0633\u0626\u0644\u06c1<\/h2>\n<p>\u0632\u0646\u062f\u06af\u06cc \u0645\u06cc\u06ba \u06a9\u0686\u06be \u0628\u06be\u06cc \u0645\u0641\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0645\u06cc\u0645\u0648 \u0628\u06be\u06cc \u0627\u0633 \u0633\u06d2 \u0645\u0633\u062a\u062b\u0646\u06cc\u0670 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u062c\u0628 \u0628\u06be\u06cc \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4 <code>useCallback<\/code> \u06cc\u0627 <code>useMemo<\/code>:<\/p>\n<p>\u06cc\u06c1 \u0646\u0648\u0679 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0645\u06cc\u06ba \u0645\u0641\u06cc\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062c\u0627\u0648\u0627 \u0627\u0633\u06a9\u0631\u067e\u0679 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0628\u0646\u0627\u0646\u0627 \u0633\u0633\u062a\u0627 \u06c1\u06d2\u06d4 50 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u0627 \u0633\u0633\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0646\u0648\u0679 \u06c1\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0644\u067e\u06cc\u0679\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9 \u062a\u06be\u0627\u0645 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0644\u0627\u06af\u062a \u0622\u0626\u06d2 \u06af\u06cc\u06d4 (\u062a\u0627\u06c1\u0645\u060c \u0627\u06af\u0631 \u067e\u0631\u0648\u0641\u0627\u0626\u0644\u0646\u06af \u0633\u06d2 \u067e\u062a\u06c1 \u0686\u0644\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0686\u06be\u0627\u0646\u0679\u0646\u0627 \u0631\u06a9\u0627\u0648\u0679 \u06a9\u0627 \u0628\u0627\u0639\u062b \u0628\u0646 \u0631\u06c1\u0627 \u06c1\u06d2\u060c <code>useMemo<\/code> \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u0627\u0633 \u0645\u0642\u0627\u0645 \u062a\u06a9 \u0645\u0639\u0642\u0648\u0644 \u06c1\u06d2\u06d4)<\/p>\n<p>\u0627\u06cc\u06a9 \u0628\u06c1\u062a\u0631 \u0646\u0642\u0637\u06c1 \u0646\u0638\u0631 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0627\u067e\u0646\u06d2 \u0627\u062c\u0632\u0627\u0621 \u06a9\u06cc \u062a\u0634\u06a9\u06cc\u0644 \u06a9\u0631\u06cc\u06ba \u062a\u0627\u06a9\u06c1 \u0648\u06c1 \u06a9\u0645 \u06a9\u062b\u0631\u062a \u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-the-problematic-page\">\u0645\u0633\u0626\u0644\u06c1 \u0648\u0627\u0644\u0627 \u0635\u0641\u062d\u06c1<\/h2>\n<p>\u0627\u0633 \u06a9\u0648 \u0639\u0645\u0644\u06cc \u0634\u06a9\u0644 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u0626\u06cc\u06d2 \u0627\u06cc\u06a9 \u062a\u0644\u0627\u0634 \u06a9\u0627 \u0635\u0641\u062d\u06c1 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u060c \u062c\u06c1\u0627\u06ba \u0627\u06cc\u06a9 \u0628\u0646\u06cc\u0627\u062f\u06cc \u062c\u0632\u0648 \u067e\u0648\u0631\u06d2 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0645\u0627\u0645 \u062d\u0627\u0644\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u0648\u0688 \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0645\u06cc\u06ba \u0646\u06d2 \u062c\u0648 \u0622\u0633\u0627\u0646 Next.js \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06c1\u06d2 \u0627\u0633\u06d2 \u06a9\u0644\u0648\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-shell\">git clone https:\/\/github.com\/Olaleye-Blessing\/freecodecamp-usecallback-usememo.git\n\n# navigate to the folder\ncd freecodecamp-usecallback-usememo\n\n# install the packages\npnpm install\n\n# start development\npnpm dev\n<\/code><\/pre>\n<p>\u062a\u0644\u0627\u0634 \u06a9\u0627 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2:<\/p>\n<p>\u0645\u0630\u06a9\u0648\u0631\u06c1 \u0628\u0627\u0644\u0627 \u062a\u0645\u0627\u0645 \u0630\u06cc\u0644\u06cc \u0627\u062c\u0632\u0627\u0621 \u0631\u06cc\u0627\u0633\u062a \u0627\u0648\u0631 \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u06c1 \u0633\u0628 \u0627\u067e\u0646\u06cc \u0631\u06cc\u0627\u0633\u062a\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0641\u0639\u0627\u0644 \u0627\u0633 \u0633\u06d2 \u0627\u062e\u0630 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba: <code>SearchPage<\/code> \u0639\u0646\u0635\u0631<\/p>\n<p>\u06c1\u0645 \u0628\u0686\u0648\u06ba \u06a9\u06d2 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 \u06cc\u06c1 \u0635\u0631\u0641 UI \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0646 \u06a9\u06d2 \u067e\u0627\u0633 \u06a9\u0648\u0626\u06cc \u0645\u0646\u0637\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>SearchPage<\/code> \u0627\u062c\u0632\u0627\u0621 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { ChangeEvent, useEffect, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack\/react-query\";\nimport {\n  fetchColors,\n  fetchCountries,\n  fetchModes,\n  fetchProducts,\n} from \".\/utils\";\nimport { Header } from \".\/_components\/header\";\nimport { FilterDrawer } from \".\/_components\/filter-drawer\";\nimport { ProductTable } from \".\/_components\/products-table\";\nimport { FilterChips } from \".\/_components\/filter-chips\";\nimport { usePathname, useRouter, useSearchParams } from \"next\/navigation\";\nimport { FilterState, LocalSortField, SortDir, SortField } from \".\/interfaces\";\n\nconst DEFAULTS: FilterState = {\n  query: \"\",\n  country: \"\",\n  color: \"\",\n  mode: \"\",\n  minPrice: \"\",\n  maxPrice: \"\",\n  sortField: \"name\",\n  sortDir: \"asc\",\n};\n\nexport default function SearchPage() {\n  const router = useRouter();\n  const pathname = usePathname();\n  const searchParams = useSearchParams();\n\n  const [drawerOpen, setDrawerOpen] = useState(false);\n\n  const [localSort, setLocalSort] = useState<{\n    field: LocalSortField;\n    dir: \"asc\" | \"desc\";\n  } | null>(null);\n\n  const searchRef = useRef<htmlinputelement>(null);\n  const searchTimerRef = useRef<returntype settimeout=\"\"> | null>(null);\n\n  const filters: FilterState = {\n    query: searchParams.get(\"q\") ?? DEFAULTS.query,\n    country: searchParams.get(\"country\") ?? DEFAULTS.country,\n    color: searchParams.get(\"color\") ?? DEFAULTS.color,\n    mode: searchParams.get(\"mode\") ?? DEFAULTS.mode,\n    minPrice: searchParams.get(\"minPrice\") ?? DEFAULTS.minPrice,\n    maxPrice: searchParams.get(\"maxPrice\") ?? DEFAULTS.maxPrice,\n    sortField:\n      (searchParams.get(\"sortField\") as SortField) ?? DEFAULTS.sortField,\n    sortDir: (searchParams.get(\"sortDir\") as SortDir) ?? DEFAULTS.sortDir,\n  };\n\n  const apiFilters = {\n    query: filters.query,\n    country: filters.country || undefined,\n    color: filters.color || undefined,\n    mode: filters.mode || undefined,\n    minPrice: filters.minPrice ? Number(filters.minPrice) : undefined,\n    maxPrice: filters.maxPrice ? Number(filters.maxPrice) : undefined,\n    sortField: filters.sortField,\n    sortDir: filters.sortDir,\n  };\n\n  const productsQuery = useQuery({\n    queryKey: [\"products\", apiFilters],\n    queryFn: () => fetchProducts(apiFilters),\n  });\n\n  const countriesQuery = useQuery({\n    queryKey: [\"countries\"],\n    queryFn: fetchCountries,\n    staleTime: Infinity,\n  });\n\n  const colorsQuery = useQuery({\n    queryKey: [\"colors\"],\n    queryFn: fetchColors,\n    staleTime: Infinity,\n  });\n\n  const modesQuery = useQuery({\n    queryKey: [\"modes\"],\n    queryFn: fetchModes,\n    staleTime: Infinity,\n  });\n\n  \/\/ Updates the filter in the drawer\n  const setFilters = (partial: Partial<filterstate>) => {\n    const next = new URLSearchParams(searchParams.toString());\n    const merged = { ...filters, ...partial };\n\n    const keyMap: Record<keyof filterstate=\"\" string=\"\"> = {\n      query: \"q\",\n      country: \"country\",\n      color: \"color\",\n      mode: \"mode\",\n      minPrice: \"minPrice\",\n      maxPrice: \"maxPrice\",\n      sortField: \"sortField\",\n      sortDir: \"sortDir\",\n    };\n\n    (Object.keys(merged) as (keyof FilterState)[]).forEach((k) => {\n      const paramKey = keyMap[k];\n      const val = merged[k];\n      const def = DEFAULTS[k];\n      if (val && val !== def) {\n        next.set(paramKey, val);\n      } else {\n        next.delete(paramKey);\n      }\n    });\n\n    router.push(`({pathname}?){next.toString()}`, { scroll: false });\n  };\n\n  const resetFilters = () => {\n    router.push(pathname, { scroll: false });\n  };\n\n  const handleQueryChange = (e: ChangeEvent<htmlinputelement>) => {\n    const val = e.target.value;\n\n    if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n\n    searchTimerRef.current = setTimeout(() => {\n      setFilters({ query: val });\n    }, 400);\n  };\n\n  const handleClearQuery = () => {\n    if (searchRef.current) {\n      searchRef.current.value = \"\";\n    }\n\n    setFilters({ query: \"\" });\n  };\n\n  const handleColumnClick = (field: LocalSortField) => {\n    setLocalSort((prev) => {\n      if (!prev || prev.field !== field) return { field, dir: \"asc\" };\n\n      if (prev.dir === \"asc\") return { field, dir: \"desc\" };\n\n      return null;\n    });\n  };\n\n  const hasPriceFilter = filters.minPrice || filters.maxPrice;\n  const priceLabel = [\n    filters.minPrice ? `$${filters.minPrice}` : null,\n    filters.maxPrice ? `$${filters.maxPrice}` : null,\n  ]\n    .filter(Boolean)\n    .join(\" - \");\n\n  const activeFilterCount = [\n    filters.country,\n    filters.color,\n    filters.mode,\n    filters.minPrice,\n    filters.maxPrice,\n  ].filter(Boolean).length;\n\n  let sortedProducts = [...(productsQuery.data || [])];\n  if (localSort) {\n    sortedProducts = [...sortedProducts].sort((a, b) => {\n      const aVal = a[localSort.field];\n      const bVal = b[localSort.field];\n      const cmp =\n        typeof aVal === \"string\"\n          ? aVal.localeCompare(bVal as string)\n          : (aVal as number) - (bVal as number);\n      return localSort.dir === \"desc\" ? -cmp : cmp;\n    });\n  }\n\n  useEffect(() => {\n    return () => {\n      if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n    };\n  }, []);\n\n  return (\n    <div classname=\"min-h-screen bg-stone-50\">\n      <header query=\"{filters.query}\" handleclearquery=\"{handleClearQuery}\" ontogglefilters=\"{()\"> setDrawerOpen((v) => !v)}\n        activeFilterCount={activeFilterCount}\n        searchRef={searchRef}\n        handleChange={handleQueryChange}\n      \/>\n\n      <filterdrawer open=\"{drawerOpen}\" onclose=\"{()\"> setDrawerOpen(false)}\n        filters={filters}\n        onChange={setFilters}\n        onReset={resetFilters}\n        countries={countriesQuery.data ?? []}\n        colors={colorsQuery.data ?? []}\n        modes={modesQuery.data ?? []}\n        activeFilterCount={activeFilterCount}\n      \/>\n\n      <main classname=\"max-w-6xl mx-auto px-4 py-6\">\n        {activeFilterCount > 0 && (\n          <filterchips filters=\"{filters}\" setfilters=\"{setFilters}\" haspricefilter=\"{hasPriceFilter}\" pricelabel=\"{priceLabel}\" resetfilters=\"{resetFilters}\"\/>\n        )}\n\n        <producttable products=\"{sortedProducts}\" isloading=\"{productsQuery.isLoading}\" handlecolumnclick=\"{handleColumnClick}\" localsort=\"{localSort}\"\/>\n      <\/main>\n    <\/filterdrawer><\/header><\/div>\n  );\n}\n<\/htmlinputelement><\/keyof><\/filterstate><\/returntype><\/htmlinputelement><\/code><\/pre>\n<p>\u06a9\u06c1 <code>SearchPage<\/code> \u062c\u0632\u0648 \u0635\u0641\u062d\u06c1 \u06a9\u0648 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u06a9\u0627\u0631 \u062a\u0645\u0627\u0645 \u0645\u0646\u0637\u0642\u0648\u06ba \u067e\u0631 \u0646\u0638\u0631 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p>\u06a9\u06c1 <code>products<\/code>\u060c <code>countries<\/code>\u060c <code>colors<\/code>\u0627\u0648\u0631 <code>modes<\/code>. \u06cc\u06c1 \u06af\u0632\u0631 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <code>countries<\/code>\u060c <code>colors<\/code> \u0627\u0648\u0631 <code>modes<\/code> \u062f\u0631\u0627\u0632 \u06a9\u06d2 \u0627\u062c\u0632\u0627\u0621 \u067e\u0631<\/p>\n<\/li>\n<li>\n<p>\u062f\u0631\u0627\u0632 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u0648 \u0679\u0631\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0631\u06a9\u0627\u0631 \u0627\u0641\u0639\u0627\u0644 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u060c \u0648\u063a\u06cc\u0631\u06c1\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1\u0627\u06ba \u0645\u0633\u0626\u0644\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06af\u0631 \u0631\u06cc\u0627\u0633\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u062f\u0644 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u062a\u0645\u0627\u0645 \u0627\u0641\u0639\u0627\u0644 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>SearchPage<\/code> \u0639\u0646\u0635\u0631 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 <code>isLoading<\/code> \u067e\u0631 <code>useQuery<\/code> \u0645\u0635\u0646\u0648\u0639\u0627\u062a (<code>productsQuery<\/code>) \u0633\u06d2 \u0628\u062f\u0644 \u06af\u06cc\u0627\u06d4 <code>false<\/code> \u06a9\u0648 <code>true<\/code>\u062a\u0645\u0627\u0645 \u0627\u0641\u0639\u0627\u0644 \u0627\u0648\u0631 \u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1 \u0642\u062f\u0631\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u06cc \u0686\u06cc\u0632 \u062c\u0648 \u0630\u06c1\u0646 \u0645\u06cc\u06ba \u0622\u062a\u06cc \u06c1\u06d2 \u0648\u06c1 \u06c1\u06d2 \u06a9\u06cc\u0634\u0646\u06af \u0641\u0646\u06a9\u0634\u0646\u0632 \u0627\u0648\u0631 \u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2: <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code>. \u062c\u0628 \u06a9\u06c1 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u06c1 \u0627\u0633 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u063a\u06cc\u0631 \u0636\u0631\u0648\u0631\u06cc \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0628\u06c1\u062a\u0631 \u062d\u0644 \u06cc\u06c1 \u06c1\u0648\u06af\u0627 \u06a9\u06c1 \u0631\u06cc\u0627\u0633\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u0642\u0631\u06cc\u0628 \u0645\u0646\u062a\u0642\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u062c\u06c1\u0627\u06ba \u0648\u06c1 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-how-to-move-state-down\">\u06a9\u0633\u06cc \u0631\u06cc\u0627\u0633\u062a \u06a9\u0648 \u06a9\u06cc\u0633\u06d2 \u0646\u06cc\u0686\u06d2 \u0645\u0646\u062a\u0642\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/h3>\n<p>\u06cc\u06c1\u0627\u06ba \u062e\u06cc\u0627\u0644 \u06c1\u06d2: \u0627\u06af\u0631 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u062c\u0632\u0648 \u06a9\u0648 \u0631\u06cc\u0627\u0633\u062a \u06cc\u0627 \u0627\u0641\u0639\u0627\u0644 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u062c\u0632\u0648 \u06a9\u0648 \u0627\u0633 \u06a9\u0627 \u0645\u0627\u0644\u06a9 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u0627\u06af\u0631 \u0628\u0686\u06d2 \u06a9\u0627 \u062c\u0632\u0648 \u0627\u067e\u0646\u06cc \u062d\u0627\u0644\u062a \u06a9\u0627 \u062e\u0648\u062f \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u06a9\u06cc \u062d\u0627\u0644\u062a \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0648\u0627\u0644\u062f\u06cc\u0646 \u06a9\u0627 \u062c\u0632\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06af\u0627\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0628\u06c1\u0646 \u0628\u06be\u0627\u0626\u06cc\u0648\u06ba \u06a9\u06cc \u062d\u0627\u0644\u062a \u0627\u0648\u0631 \u0641\u0639\u0627\u0644\u06cc\u062a \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0646\u0648\u0679 \u06a9\u06d2 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0631\u06c1\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u06d2 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba\u060c \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u062a\u0646\u0627 \u0646\u06cc\u0686\u06d2 \u0646\u06c1 \u0644\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u062c\u0627\u0646\u0686\u0646\u0627 \u06cc\u0627 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06d2\u06d4 \u0645\u0642\u0635\u062f \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u06c1\u0631 \u0679\u06a9\u0691\u06d2 \u06a9\u0648 \u0645\u0645\u06a9\u0646\u06c1 \u06af\u06c1\u0631\u06d2 \u062c\u0632\u0648 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u06be\u067e\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4 \u0645\u0642\u0635\u062f \u0631\u06cc\u0627\u0633\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0646\u0686\u0644\u06cc \u0633\u0637\u062d \u067e\u0631 \u0631\u06a9\u06be\u0646\u0627 \u06c1\u06d2 \u062c\u0648 \u0627\u0628 \u0628\u06be\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0632\u0648\u06ba \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-move-producttable-logic-to-its-component\">\u067e\u0631\u0648\u0688\u06a9\u0679 \u0679\u06cc\u0628\u0644 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u062c\u0632\u0648 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u0627\u06af\u0631 \u0622\u067e \u0645\u0635\u0646\u0648\u0639\u0627\u062a \u06a9\u0648 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2 \u06a9\u06c1 \u0627\u0633 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0635\u0631\u0641 \u0627\u062c\u0632\u0627\u0621 \u06c1\u06cc\u06ba: <code>ProductsTable<\/code>. \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0627\u067e\u0646\u06cc \u062f\u0631\u0622\u0645\u062f \u0627\u0648\u0631 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>ProductsTable<\/code>.<\/p>\n<p>\u06a9\u06c1 <code>ProductsComponent<\/code> \u06cc\u06c1 \u0645\u0648\u062c\u0648\u062f\u06c1 \u062d\u0627\u0644\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0628\u0637\u0648\u0631 \u067e\u0631\u0648\u067e\u0633 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\ninterface ProductTableProps {\n  products: Product[];\n  isLoading: boolean;\n  handleColumnClick: (field: LocalSortField) => void;\n  localSort: { field: LocalSortField; dir: SortDir } | null;\n}\n\nexport function ProductTable({\n  products,\n  isLoading,\n  handleColumnClick,\n  localSort,\n}: ProductTableProps) {\n  \/\/ renders the UI using the props\n}\n<\/code><\/pre>\n<p>\u0627\u0628 <code>ProductTable<\/code> \u0627\u0633 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u062f\u0631\u0622\u0645\u062f \u0627\u0648\u0631 \u0645\u0646\u0638\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">interface ProductTableProps {\n  filters: FilterState;\n}\n\nexport function ProductTable({ filters }: ProductTableProps) {\n  const [localSort, setLocalSort] = useState<{\n    field: LocalSortField;\n    dir: \"asc\" | \"desc\";\n  } | null>(null);\n\n  const apiFilters = {\n    query: filters.query,\n    country: filters.country || undefined,\n    color: filters.color || undefined,\n    mode: filters.mode || undefined,\n    minPrice: filters.minPrice ? Number(filters.minPrice) : undefined,\n    maxPrice: filters.maxPrice ? Number(filters.maxPrice) : undefined,\n    sortField: filters.sortField,\n    sortDir: filters.sortDir,\n  };\n\n  const { data: products = [], isLoading } = useQuery({\n    queryKey: [\"products\", apiFilters],\n    queryFn: () => fetchProducts(apiFilters),\n  });\n\n  const handleColumnClick = (field: LocalSortField) => {\n    setLocalSort((prev) => {\n      if (!prev || prev.field !== field) return { field, dir: \"asc\" };\n      if (prev.dir === \"asc\") return { field, dir: \"desc\" };\n\n      return null;\n    });\n  };\n\n  let sortedProducts = products;\n  if (localSort) {\n    sortedProducts = [...products].sort((a, b) => {\n      const aVal = a[localSort.field];\n      const bVal = b[localSort.field];\n      const cmp =\n        typeof aVal === \"string\"\n          ? aVal.localeCompare(bVal as string)\n          : (aVal as number) - (bVal as number);\n      return localSort.dir === \"desc\" ? -cmp : cmp;\n    });\n  }\n\n  return <>{\/*== renders the UI using the props ==*\/}>;\n}\n<\/code><\/pre>\n<p>\u0627\u0628 \u062c\u0628 <code>isLoading<\/code> \u062a\u0628\u062f\u06cc\u0644\u06cc <code>SearchPage<\/code> \u062c\u0632\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1 \u0627\u0642\u062f\u0627\u0631 \u0627\u0648\u0631 \u062f\u06cc\u06af\u0631 \u0627\u0641\u0639\u0627\u0644\u06d4 <code>SearchPage<\/code> \u0627\u062c\u0632\u0627\u0621 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u062f\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0635\u0631\u0641 \u0648\u06c1\u06cc \u0627\u0642\u062f\u0627\u0631 \u0627\u0648\u0631 \u0627\u0641\u0639\u0627\u0644 \u06c1\u06cc\u06ba \u062c\u0648 \u06cc\u06c1\u0627\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0626\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 <code>sortedProducts<\/code> \u0627\u0648\u0631 <code>handleColumnClick<\/code>.<\/p>\n<p>\u06a9\u06c1 <code>SearchPage<\/code> \u0627\u062c\u0632\u0627\u0621 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { ChangeEvent, useEffect, useRef, useState } from \"react\";\nimport { useQuery } from \"@tanstack\/react-query\";\nimport { fetchColors, fetchCountries, fetchModes } from \".\/utils\";\nimport { Header } from \".\/_components\/header\";\nimport { FilterDrawer } from \".\/_components\/filter-drawer\";\nimport { ProductTable } from \".\/_components\/products-table\";\nimport { FilterChips } from \".\/_components\/filter-chips\";\nimport { usePathname, useRouter, useSearchParams } from \"next\/navigation\";\nimport { FilterState, SortDir, SortField } from \".\/interfaces\";\n\nconst DEFAULTS: FilterState = {\n  query: \"\",\n  country: \"\",\n  color: \"\",\n  mode: \"\",\n  minPrice: \"\",\n  maxPrice: \"\",\n  sortField: \"name\",\n  sortDir: \"asc\",\n};\n\nexport default function SearchPage() {\n  const router = useRouter();\n  const pathname = usePathname();\n  const searchParams = useSearchParams();\n\n  const [drawerOpen, setDrawerOpen] = useState(false);\n\n  const searchRef = useRef<htmlinputelement>(null);\n  const searchTimerRef = useRef<returntype settimeout=\"\"> | null>(null);\n\n  const filters: FilterState = {\n    query: searchParams.get(\"q\") ?? DEFAULTS.query,\n    country: searchParams.get(\"country\") ?? DEFAULTS.country,\n    color: searchParams.get(\"color\") ?? DEFAULTS.color,\n    mode: searchParams.get(\"mode\") ?? DEFAULTS.mode,\n    minPrice: searchParams.get(\"minPrice\") ?? DEFAULTS.minPrice,\n    maxPrice: searchParams.get(\"maxPrice\") ?? DEFAULTS.maxPrice,\n    sortField:\n      (searchParams.get(\"sortField\") as SortField) ?? DEFAULTS.sortField,\n    sortDir: (searchParams.get(\"sortDir\") as SortDir) ?? DEFAULTS.sortDir,\n  };\n\n  const countriesQuery = useQuery({\n    queryKey: [\"countries\"],\n    queryFn: fetchCountries,\n    staleTime: Infinity,\n  });\n\n  const colorsQuery = useQuery({\n    queryKey: [\"colors\"],\n    queryFn: fetchColors,\n    staleTime: Infinity,\n  });\n\n  const modesQuery = useQuery({\n    queryKey: [\"modes\"],\n    queryFn: fetchModes,\n    staleTime: Infinity,\n  });\n\n  \/\/ Updates the filter in the drawer\n  const setFilters = (partial: Partial<filterstate>) => {\n    const next = new URLSearchParams(searchParams.toString());\n    const merged = { ...filters, ...partial };\n\n    const keyMap: Record<keyof filterstate=\"\" string=\"\"> = {\n      query: \"q\",\n      country: \"country\",\n      color: \"color\",\n      mode: \"mode\",\n      minPrice: \"minPrice\",\n      maxPrice: \"maxPrice\",\n      sortField: \"sortField\",\n      sortDir: \"sortDir\",\n    };\n\n    (Object.keys(merged) as (keyof FilterState)[]).forEach((k) => {\n      const paramKey = keyMap[k];\n      const val = merged[k];\n      const def = DEFAULTS[k];\n      if (val && val !== def) {\n        next.set(paramKey, val);\n      } else {\n        next.delete(paramKey);\n      }\n    });\n\n    router.push(`({pathname}?){next.toString()}`, { scroll: false });\n  };\n\n  const resetFilters = () => {\n    router.push(pathname, { scroll: false });\n  };\n\n  const handleQueryChange = (e: ChangeEvent<htmlinputelement>) => {\n    const val = e.target.value;\n\n    if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n\n    searchTimerRef.current = setTimeout(() => {\n      setFilters({ query: val });\n    }, 400);\n  };\n\n  const handleClearQuery = () => {\n    if (searchRef.current) {\n      searchRef.current.value = \"\";\n    }\n\n    setFilters({ query: \"\" });\n  };\n\n  const hasPriceFilter = filters.minPrice || filters.maxPrice;\n  const priceLabel = [\n    filters.minPrice ? `$${filters.minPrice}` : null,\n    filters.maxPrice ? `$${filters.maxPrice}` : null,\n  ]\n    .filter(Boolean)\n    .join(\" - \");\n\n  const activeFilterCount = [\n    filters.country,\n    filters.color,\n    filters.mode,\n    filters.minPrice,\n    filters.maxPrice,\n  ].filter(Boolean).length;\n\n  useEffect(() => {\n    return () => {\n      if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n    };\n  }, []);\n\n  return (\n    <div classname=\"min-h-screen bg-stone-50\">\n      <header query=\"{filters.query}\" onchange=\"{setFilters}\" handleclearquery=\"{handleClearQuery}\" ontogglefilters=\"{()\"> setDrawerOpen((v) => !v)}\n        activeFilterCount={activeFilterCount}\n        searchRef={searchRef}\n        handleChange={handleQueryChange}\n      \/>\n\n      <filterdrawer open=\"{drawerOpen}\" onclose=\"{()\"> setDrawerOpen(false)}\n        filters={filters}\n        onChange={setFilters}\n        onReset={resetFilters}\n        countries={countriesQuery.data ?? []}\n        colors={colorsQuery.data ?? []}\n        modes={modesQuery.data ?? []}\n        activeFilterCount={activeFilterCount}\n      \/>\n\n      <main classname=\"max-w-6xl mx-auto px-4 py-6\">\n        {activeFilterCount > 0 && (\n          <filterchips filters=\"{filters}\" setfilters=\"{setFilters}\" haspricefilter=\"{hasPriceFilter}\" pricelabel=\"{priceLabel}\" resetfilters=\"{resetFilters}\"\/>\n        )}\n\n        <producttable filters=\"{filters}\"\/>\n      <\/main>\n    <\/filterdrawer><\/header><\/div>\n  );\n}\n<\/htmlinputelement><\/keyof><\/filterstate><\/returntype><\/htmlinputelement><\/code><\/pre>\n<p>\u06a9\u06c1 <code>SearchPage<\/code> \u062c\u0632\u0648 \u0627\u0628 \u067e\u0631\u0648\u0688\u06a9\u0679 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0627\u0648\u0631 \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-move-filtering-logic-to-its-component\">\u0641\u0644\u0679\u0631\u0646\u06af \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u062c\u0632\u0648 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u0627\u0633 \u06a9\u0627\u0645 \u06a9\u0648 \u067e\u0648\u0631\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0631\u06cc\u0627\u0633\u062a\u06cc\u06ba\u060c \u0688\u06cc\u0679\u0627 \u0627\u0648\u0631 \u0627\u0641\u0639\u0627\u0644 \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p><code>drawerOpen<\/code>    \u0627\u0648\u0631 <code>setDrawerOpen<\/code> \u0641\u0644\u0679\u0631 \u062f\u0631\u0627\u0632 \u06a9\u0648 \u06a9\u0646\u0679\u0631\u0648\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>countries<\/code>\u060c <code>colors<\/code> \u0627\u0648\u0631 <code>modes<\/code> \u0688\u06cc\u0679\u0627 \u062c\u0648 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u0627\u062e\u062a\u06cc\u0627\u0631\u0627\u062a \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>activeFilterCount<\/code>    \u0641\u0639\u0627\u0644 \u0641\u0644\u0679\u0631\u0632 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0641\u06cc \u0627\u0644\u062d\u0627\u0644\u060c \u0641\u0644\u0679\u0631\u0646\u06af \u06a9\u06d2 \u062f\u0648 \u0627\u062c\u0632\u0627\u0621 \u06c1\u06cc\u06ba: \u067e\u06c1\u0644\u0627 \u0627\u0646\u062f\u0631 \u06a9\u0627 \u0628\u0679\u0646 \u06c1\u06d2\u06d4 <code>Header<\/code> \u0627\u062c\u0632\u0627\u0621 \u062c\u06cc\u0633\u06d2:<\/p>\n<pre><code class=\"language-typescript\"><button onclick=\"{onToggleFilters}\" classname=\"relative ml-auto flex items-center gap-2 px-3 py-2 text-sm text-black font-medium border border-stone-300 rounded-lg hover:bg-stone-100 transition\">\n  <slidershorizontal classname=\"w-4 h-4\"\/>\n  <span classname=\"hidden sm:inline\">Filters<\/span>\n  {activeFilterCount > 0 && (\n    <span classname=\"absolute -top-1.5 -right-1.5 flex items-center justify-center \n                             w-5 h-5 rounded-full bg-stone-900 text-white text-xs font-bold\">\n      {activeFilterCount}\n    <\/span>\n  )}\n<\/button>;\n<\/code><\/pre>\n<p>\u062f\u0648\u0633\u0631\u0627 \u06c1\u06d2\u06d4 <code>FilterDrawer<\/code> \u0627\u062c\u0632\u0627\u0621 \u062c\u06cc\u0633\u06d2:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { X, RotateCcw } from \"lucide-react\";\nimport { FilterState } from \"..\/interfaces\";\nimport { SortSection } from \".\/filter\/sort-section\";\nimport { NarrowResultsSection } from \".\/filter\/narrow-result-section\";\n\ninterface FilterDrawerProps {\n  open: boolean;\n  onClose: () => void;\n  filters: FilterState;\n  onChange: (partial: Partial<filterstate>) => void;\n  onReset: () => void;\n  countries: string[];\n  colors: string[];\n  modes: string[];\n  activeFilterCount: number;\n}\n\nexport function FilterDrawer({\n  open,\n  onClose,\n  filters,\n  onChange,\n  onReset,\n  countries,\n  colors,\n  modes,\n  activeFilterCount,\n}: FilterDrawerProps) {\n  const drawerRef = useRef<htmldivelement>(null);\n\n  \/\/ Close on Escape\n  useEffect(() => {\n    const handler = (e: KeyboardEvent) => {\n      if (e.key === \"Escape\") onClose();\n    };\n    document.addEventListener(\"keydown\", handler);\n    return () => document.removeEventListener(\"keydown\", handler);\n  }, [onClose]);\n\n  \/\/ Prevent body scroll while open\n  useEffect(() => {\n    document.body.style.overflow = open ? \"hidden\" : \"\";\n    return () => {\n      document.body.style.overflow = \"\";\n    };\n  }, [open]);\n\n  return (\n    <>\n      {\/* Backdrop *\/}\n      \n\n      {\/* Drawer panel *\/}\n      <aside ref=\"{drawerRef}\" classname=\"{`fixed\" top-0=\"\" right-0=\"\" z-50=\"\" h-full=\"\" w-80=\"\" bg-white=\"\" shadow-2xl=\"\" flex=\"\" flex-col=\"\" transition-transform=\"\" duration-300=\"\" ease-in-out=\"\" :=\"\" aria-hidden=\"{!open}\">\n        {\/* Header *\/}\n        <p>\n          <h2 classname=\"font-semibold text-stone-900\">\n            Filters & Sort\n            {activeFilterCount > 0 && (\n              <span classname=\"ml-2 text-xs bg-stone-900 text-white px-1.5 py-0.5 rounded-full\">\n                {activeFilterCount}\n              <\/span>\n            )}\n          <\/h2>\n          <button onclick=\"{onClose}\" classname=\"p-1.5 rounded-md hover:bg-stone-100 transition\" aria-label=\"Close filters\">\n            <x classname=\"w-5 h-5 text-stone-600\"\/>\n          <\/button>\n        <\/p>\n\n        \n\n        {\/* Footer *\/}\n        {activeFilterCount > 0 && (\n          <p>\n            <button onclick=\"{()\"> {\n                onReset();\n                onClose();\n              }}\n              className=\"w-full flex items-center justify-center gap-2 px-4 py-2.5 \n                         border border-stone-300 rounded-lg text-sm font-medium \n                         hover:bg-stone-100 transition text-stone-700\"\n            >\n              <rotateccw classname=\"w-4 h-4\"\/>\n              Clear all filters\n            <\/button>\n          <\/p>\n        )}\n      <\/aside>\n    >\n  );\n}\n<\/htmldivelement><\/filterstate><\/code><\/pre>\n<p>\u0622\u067e \u062f\u0648 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u0627\u06cc\u06a9 \u062c\u0632\u0648 \u0645\u06cc\u06ba \u062c\u0648\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>Filter<\/code> \u0648\u06c1 \u062c\u0632 \u062c\u0648 \u0627\u0633 \u062a\u0645\u0627\u0645 \u0645\u0646\u0637\u0642 \u06a9\u0627 \u0645\u0627\u0644\u06a9 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">import { RotateCcw, SlidersHorizontal, X } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { SortSection } from \".\/filter\/sort-section\";\nimport { NarrowResultsSection } from \".\/filter\/narrow-result-section\";\nimport { FilterState } from \"..\/interfaces\";\nimport { usePathname, useRouter } from \"next\/navigation\";\nimport { useQuery } from \"@tanstack\/react-query\";\nimport { fetchColors, fetchCountries, fetchModes } from \"..\/utils\";\n\ninterface FilterProps {\n  filters: FilterState;\n  onChange: (partial: Partial<filterstate>) => void;\n}\n\nconst Filter = ({ filters, onChange }: FilterProps) => {\n  const { data: countries = [] } = useQuery({\n    queryKey: [\"countries\"],\n    queryFn: fetchCountries,\n    staleTime: Infinity,\n  });\n\n  const { data: colors = [] } = useQuery({\n    queryKey: [\"colors\"],\n    queryFn: fetchColors,\n    staleTime: Infinity,\n  });\n\n  const { data: modes = [] } = useQuery({\n    queryKey: [\"modes\"],\n    queryFn: fetchModes,\n    staleTime: Infinity,\n  });\n\n  const router = useRouter();\n  const pathname = usePathname();\n  const [drawerOpen, setDrawerOpen] = useState(false);\n\n  const drawerRef = useRef<htmldivelement>(null);\n\n  const onClose = () => setDrawerOpen(false);\n  const openDrawer = () => setDrawerOpen(true);\n  const resetFilters = () => {\n    onClose();\n    router.push(pathname, { scroll: false });\n  };\n\n  const activeFilterCount = [\n    filters.country,\n    filters.color,\n    filters.mode,\n    filters.minPrice,\n    filters.maxPrice,\n  ].filter(Boolean).length;\n\n  \/\/ Close on Escape\n  useEffect(() => {\n    const handler = (e: KeyboardEvent) => {\n      if (e.key === \"Escape\") setDrawerOpen(false);\n    };\n    document.addEventListener(\"keydown\", handler);\n    return () => document.removeEventListener(\"keydown\", handler);\n  }, []);\n\n  \/\/ Prevent body scroll while open\n  useEffect(() => {\n    document.body.style.overflow = drawerOpen ? \"hidden\" : \"\";\n    return () => {\n      document.body.style.overflow = \"\";\n    };\n  }, [drawerOpen]);\n\n  return (\n    <>\n      <button onclick=\"{openDrawer}\" classname=\"relative ml-auto flex items-center gap-2 px-3 py-2 text-sm text-black font-medium border border-stone-300 rounded-lg hover:bg-stone-100 transition\">\n        <slidershorizontal classname=\"w-4 h-4\"\/>\n        <span classname=\"hidden sm:inline\">Filters<\/span>\n        {activeFilterCount > 0 && (\n          <span classname=\"absolute -top-1.5 -right-1.5 flex items-center justify-center \n                             w-5 h-5 rounded-full bg-stone-900 text-white text-xs font-bold\">\n            {activeFilterCount}\n          <\/span>\n        )}\n      <\/button>\n      {\/* Backdrop *\/}\n      \n\n      {\/* Drawer panel *\/}\n      <aside ref=\"{drawerRef}\" classname=\"{`fixed\" top-0=\"\" right-0=\"\" z-50=\"\" h-full=\"\" w-80=\"\" bg-white=\"\" shadow-2xl=\"\" flex=\"\" flex-col=\"\" transition-transform=\"\" duration-300=\"\" ease-in-out=\"\" :=\"\" aria-hidden=\"{!drawerOpen}\">\n        {\/* Header *\/}\n        <p>\n          <h2 classname=\"font-semibold text-stone-900\">\n            Filters & Sort\n            {activeFilterCount > 0 && (\n              <span classname=\"ml-2 text-xs bg-stone-900 text-white px-1.5 py-0.5 rounded-full\">\n                {activeFilterCount}\n              <\/span>\n            )}\n          <\/h2>\n          <button onclick=\"{onClose}\" classname=\"p-1.5 rounded-md hover:bg-stone-100 transition\" aria-label=\"Close filters\">\n            <x classname=\"w-5 h-5 text-stone-600\"\/>\n          <\/button>\n        <\/p>\n\n        \n\n        {\/* Footer *\/}\n        {activeFilterCount > 0 && (\n          <p>\n            <button onclick=\"{resetFilters}\" classname=\"w-full flex items-center justify-center gap-2 px-4 py-2.5 \n                         border border-stone-300 rounded-lg text-sm font-medium \n                         hover:bg-stone-100 transition text-stone-700\">\n              <rotateccw classname=\"w-4 h-4\"\/>\n              Clear all filters\n            <\/button>\n          <\/p>\n        )}\n      <\/aside>\n    >\n  );\n};\n\nexport default Filter;\n<\/htmldivelement><\/filterstate><\/code><\/pre>\n<p>\u06c1\u0645 \u0627\u0633\u06d2 \u0645\u0632\u06cc\u062f \u062a\u0631\u0642\u06cc \u062f\u06d2 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062a\u0648\u062c\u06c1 \u0641\u0631\u0645\u0627\u0626\u06cc\u06ba <code>NarrowResultsSection<\/code> \u06cc\u06c1 \u0648\u0627\u062d\u062f \u062c\u0632\u0648 \u06c1\u06d2 \u062c\u0648 \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u0627\u0634\u06cc\u0627\u0621 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>countries<\/code>\u060c <code>colors<\/code>\u0627\u0648\u0631 <code>modes<\/code>. \u0627\u0648\u0631 \u06c1\u0631 \u0627\u06cc\u06a9 \u0645\u06cc\u06ba <code>SelectField<\/code> \u06c1\u0645 \u0627\u0633 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0686\u06be \u0688\u06cc\u0679\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">import { FilterState } from \"..\/..\/interfaces\";\nimport { PriceRangeField } from \".\/price-range\";\nimport { SelectField } from \".\/select-field\";\n\ninterface NarrowResultsSectionProps {\n  filters: FilterState;\n  onChange: (partial: Partial<filterstate>) => void;\n  countries: string[];\n  colors: string[];\n  modes: string[];\n}\n\nexport function NarrowResultsSection({\n  filters,\n  onChange,\n  countries,\n  colors,\n  modes,\n}: NarrowResultsSectionProps) {\n  return (\n    <section classname=\"flex flex-col gap-4\">\n      <h3 classname=\"text-xs font-semibold uppercase tracking-wider text-stone-500\">\n        Narrow Results\n      <\/h3>\n\n      <selectfield label=\"Country\" value=\"{filters.country}\" options=\"{countries}\" onchange=\"{(v)\"> onChange({ country: v })}\n        placeholder=\"All countries\"\n      \/>\n\n      <selectfield label=\"Color\" value=\"{filters.color}\" options=\"{colors}\" onchange=\"{(v)\"> onChange({ color: v })}\n        placeholder=\"All colors\"\n      \/>\n\n      <selectfield label=\"Mode\" value=\"{filters.mode}\" options=\"{modes}\" onchange=\"{(v)\"> onChange({ mode: v })}\n        placeholder=\"All modes\"\n      \/>\n\n      <pricerangefield minprice=\"{filters.minPrice}\" maxprice=\"{filters.maxPrice}\" onchange=\"{onChange}\"\/>\n    <\/selectfield><\/selectfield><\/selectfield><\/section>\n  );\n}\n<\/filterstate><\/code><\/pre>\n<p>\u062a\u0645\u0627\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u0627\u0648\u067e\u0631 \u0633\u06d2 \u0644\u06d2 \u06a9\u0631 \u0646\u06cc\u0686\u06d2 \u0633\u06d2 \u06af\u0632\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0622\u067e \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u062c\u0627\u0646\u06d2 \u062f\u06d2 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>SelectField<\/code> \u06cc\u06c1 \u0627\u0633 \u06a9\u0627 \u0627\u067e\u0646\u0627 \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06c1 <code>SelectField<\/code> \u06cc\u06c1 \u0627\u0633 \u0637\u0631\u062d \u0646\u0638\u0631 \u0622\u06cc\u0627:<\/p>\n<pre><code class=\"language-typescript\">interface SelectFieldProps {\n  label: string;\n  value: string;\n  options: string[];\n  onChange: (v: string) => void;\n  placeholder: string;\n}\n\nexport function SelectField({\n  label,\n  value,\n  options,\n  onChange,\n  placeholder,\n}: SelectFieldProps) {\n  return <>{\/*=== Renders UI ===*\/}>;\n}\n<\/code><\/pre>\n<p>\u0627\u0628 \u06cc\u06c1 \u0627\u0633 \u0637\u0631\u062d \u0644\u06af\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-typescript\">import { useQuery } from \"@tanstack\/react-query\";\n\ninterface SelectFieldProps {\n  label: string;\n  value: string;\n  onChange: (v: string) => void;\n  placeholder: string;\n  queryFn(): Promise<string>;\n  queryKey: string;\n}\n\nexport function SelectField({\n  label,\n  value,\n  onChange,\n  placeholder,\n  queryFn,\n  queryKey,\n}: SelectFieldProps) {\n  const { data: options = [] } = useQuery({\n    queryKey: [queryKey],\n    queryFn: queryFn,\n    staleTime: Infinity,\n  });\n\n  return <>{\/*=== Renders UI ===*\/}>;\n}\n<\/string><\/code><\/pre>\n<p>\u06c1\u0631 \u0688\u0631\u0627\u067e \u0688\u0627\u0624\u0646 \u0627\u0628 \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0631\u06cc\u0627\u0633\u062a \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>SelectField<\/code> \u06cc\u06c1 \u0628\u06c1\u0646 \u0628\u06be\u0627\u0626\u06cc\u0648\u06ba \u06cc\u0627 \u0648\u0627\u0644\u062f\u06cc\u0646 \u06a9\u0648 \u0645\u062a\u0627\u062b\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-move-search-logic-into-its-component\">\u062a\u0644\u0627\u0634 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u062c\u0632\u0648 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u06a9\u06c1 <code>Search<\/code> \u062c\u0632\u0648 \u0648\u0627\u062d\u062f \u06c1\u06d2 \u062c\u0648 \u0688\u06cc\u0628\u0648\u0646\u0633\u0646\u06af \u0645\u0646\u0637\u0642 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (<code>searchTimerRef<\/code>\u060c <code>handleQueryChange<\/code>\u060c <code>handleClearQuery<\/code>)\u06d4 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u062c\u0632\u0648 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { Search as SearchIcon, X } from \"lucide-react\";\nimport { ChangeEvent, useEffect, useRef } from \"react\";\nimport { FilterState } from \"..\/interfaces\";\n\ninterface SearchProps {\n  query: string;\n  onChange: (partial: Partial<filterstate>) => void;\n}\n\nconst Search = ({ query, onChange }: SearchProps) => {\n  const searchRef = useRef<htmlinputelement>(null);\n  const searchTimerRef = useRef<returntype settimeout=\"\"> | null>(null);\n\n  const handleClearQuery = () => {\n    if (searchRef.current) {\n      searchRef.current.value = \"\";\n    }\n\n    onChange({ query: \"\" });\n  };\n\n  const handleQueryChange = (e: ChangeEvent<htmlinputelement>) => {\n    const val = e.target.value;\n\n    if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n\n    searchTimerRef.current = setTimeout(() => {\n      onChange({ query: val });\n    }, 400);\n  };\n\n  useEffect(() => {\n    return () => {\n      if (searchTimerRef.current) clearTimeout(searchTimerRef.current);\n    };\n  }, []);\n\n  return <p>{\/*=== Renders UI ===*\/}<\/p>;\n};\n\nexport default Search;\n<\/htmlinputelement><\/returntype><\/htmlinputelement><\/filterstate><\/code><\/pre>\n<h4 id=\"heading-move-filter-chips-into-its-component\">\u0641\u0644\u0679\u0631 \u0686\u067e \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u062c\u0632\u0648 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h4>\n<p>\u06a9\u06c1 <code>FilterChips<\/code> \u062c\u0632\u0648 \u0641\u0639\u0627\u0644 \u0641\u0644\u0679\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0686\u067e \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06c1 <code>hasPriceFilter<\/code> \u0627\u0648\u0631 <code>priceLabel<\/code> \u0642\u06cc\u0645\u062a \u062c\u0648 \u06cc\u06c1 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062c\u0632\u0648 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u06c1\u0648\u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4 <code>SearchPage<\/code>:<\/p>\n<pre><code class=\"language-typescript\">interface FilterChipsProps {\n  filters: FilterState;\n  setFilters: (partial: Partial<filterstate>) => void;\n  resetFilters: () => void;\n}\n\nexport function FilterChips({\n  filters,\n  setFilters,\n  resetFilters,\n}: FilterChipsProps) {\n  const priceLabel = [\n    filters.minPrice ? `$${filters.minPrice}` : null,\n    filters.maxPrice ? `$${filters.maxPrice}` : null,\n  ]\n    .filter(Boolean)\n    .join(\" - \");\n\n  const hasPriceFilter = filters.minPrice || filters.maxPrice;\n\n  return <>{\/*=== Renders UI ===*\/}>;\n}\n<\/filterstate><\/code><\/pre>\n<h4 id=\"heading-the-final-searchpage\">\u062d\u062a\u0645\u06cc \u062a\u0644\u0627\u0634 \u06a9\u0627 \u0635\u0641\u062d\u06c1<\/h4>\n<p>\u062a\u0645\u0627\u0645 \u062d\u0627\u0644\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0645\u0637\u0644\u0648\u0628\u06c1 \u0627\u062c\u0632\u0627\u0621 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f: <code>SearchPage<\/code> \u0627\u062c\u0632\u0627\u0621 \u06c1\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { Header } from \".\/_components\/header\";\nimport { ProductTable } from \".\/_components\/products-table\";\nimport { FilterChips } from \".\/_components\/filter-chips\";\nimport { usePathname, useRouter, useSearchParams } from \"next\/navigation\";\nimport { FilterState, SortDir, SortField } from \".\/interfaces\";\n\nconst DEFAULTS: FilterState = {\n  query: \"\",\n  country: \"\",\n  color: \"\",\n  mode: \"\",\n  minPrice: \"\",\n  maxPrice: \"\",\n  sortField: \"name\",\n  sortDir: \"asc\",\n};\n\nexport default function SearchPage() {\n  const router = useRouter();\n  const pathname = usePathname();\n  const searchParams = useSearchParams();\n\n  const filters: FilterState = {\n    query: searchParams.get(\"q\") ?? DEFAULTS.query,\n    country: searchParams.get(\"country\") ?? DEFAULTS.country,\n    color: searchParams.get(\"color\") ?? DEFAULTS.color,\n    mode: searchParams.get(\"mode\") ?? DEFAULTS.mode,\n    minPrice: searchParams.get(\"minPrice\") ?? DEFAULTS.minPrice,\n    maxPrice: searchParams.get(\"maxPrice\") ?? DEFAULTS.maxPrice,\n    sortField:\n      (searchParams.get(\"sortField\") as SortField) ?? DEFAULTS.sortField,\n    sortDir: (searchParams.get(\"sortDir\") as SortDir) ?? DEFAULTS.sortDir,\n  };\n\n  const setFilters = (partial: Partial<filterstate>) => {\n    const next = new URLSearchParams(searchParams.toString());\n    const merged = { ...filters, ...partial };\n\n    const keyMap: Record<keyof filterstate=\"\" string=\"\"> = {\n      query: \"q\",\n      country: \"country\",\n      color: \"color\",\n      mode: \"mode\",\n      minPrice: \"minPrice\",\n      maxPrice: \"maxPrice\",\n      sortField: \"sortField\",\n      sortDir: \"sortDir\",\n    };\n\n    (Object.keys(merged) as (keyof FilterState)[]).forEach((k) => {\n      const paramKey = keyMap[k];\n      const val = merged[k];\n      const def = DEFAULTS[k];\n      if (val && val !== def) {\n        next.set(paramKey, val);\n      } else {\n        next.delete(paramKey);\n      }\n    });\n\n    router.push(`({pathname}?){next.toString()}`, { scroll: false });\n  };\n\n  const resetFilters = () => {\n    router.push(pathname, { scroll: false });\n  };\n\n  const activeFilterCount = [\n    filters.country,\n    filters.color,\n    filters.mode,\n    filters.minPrice,\n    filters.maxPrice,\n  ].filter(Boolean).length;\n\n  return (\n    <div classname=\"min-h-screen bg-stone-50\">\n      <header filters=\"{filters}\" onchange=\"{setFilters}\"\/>\n\n      <main classname=\"max-w-6xl mx-auto px-4 py-6\">\n        {activeFilterCount > 0 && (\n          <filterchips filters=\"{filters}\" setfilters=\"{setFilters}\" resetfilters=\"{resetFilters}\"\/>\n        )}\n\n        <producttable filters=\"{filters}\"\/>\n      <\/main>\n    <\/div>\n  );\n}\n<\/keyof><\/filterstate><\/code><\/pre>\n<p>\u062a\u0648\u062c\u06c1 \u0641\u0631\u0645\u0627\u0626\u06cc\u06ba <code>setFilters<\/code>\u060c <code>resetFilters<\/code> \u0627\u0648\u0631 <code>activeFilterCount<\/code> \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u0648\u06c1\u0627\u06ba \u06c1\u06d2\u06d4 <code>SearchPage<\/code> \u0639\u0646\u0635\u0631 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0642\u062f\u0631 URL \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0633\u06d2 \u067e\u0691\u06be\u0646\u06d2 \u0648\u0627\u0644\u0627 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u062c\u0632\u0648 \u062c\u0628 \u0628\u06be\u06cc \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 \u0627\u0633 \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0641\u0631\u0642 \u0646\u06c1\u06cc\u06ba \u067e\u0691\u062a\u0627 \u06a9\u06c1 \u0642\u06cc\u0645\u062a \u06a9\u0627 \u062d\u0633\u0627\u0628 \u06a9\u06c1\u0627\u06ba \u0644\u06af\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-fix-your-code-before-reaching-for-these-hooks\">\u0627\u0646 \u06c1\u06a9\u0633 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u067e\u0646\u0627 \u06a9\u0648\u0688 \u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0622\u067e \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0646\u06d2 \u06a9\u0627 \u0644\u0627\u0644\u0686 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>useCallback<\/code> \u06cc\u0627 <code>useMemo<\/code> \u062c\u0628 \u0644\u0627\u0645\u062d\u062f\u0648\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06d2 \u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a \u0627\u06a9\u062b\u0631 \u0644\u0627\u0645\u062d\u062f\u0648\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0646\u062a\u06cc\u062c\u06c1 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u0630\u06cc\u0644\u06cc \u0627\u062c\u0632\u0627\u0621 \u0645\u06cc\u06ba <code>useEffect<\/code> \u06cc\u06c1 \u0627\u0639\u062a\u0631\u0627\u0636 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0645\u062c\u06be\u0646\u0627 \u06c1\u0645\u06cc\u0634\u06c1 \u0628\u06c1\u062a\u0631 \u06c1\u06d2 \u06a9\u06c1 \u0644\u0648\u067e \u06a9\u06cc\u0648\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0648\u062c\u06c1 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0627\u0633 \u0645\u062b\u0627\u0644 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u06cc\u06ba:<\/p>\n<pre><code class=\"language-typescript\">\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { fetchUsers, Filter, User } from \".\/utils\";\n\ninterface UserListProps {\n  filters: Filter;\n  onLoad(data: User[]): void;\n  users: User[];\n}\n\nfunction UserList({ filters, onLoad, users }: UserListProps) {\n  console.count(\"__ USER LIST __\");\n\n  useEffect(() => {\n    fetchUsers(filters).then((data) => {\n      onLoad(data);\n    });\n  }, [filters, onLoad]);\n\n  return (\n    <ul classname=\"h-screen flex items-center justify-center flex-col\">\n      {users.map((u) => (\n        <li key=\"{u.id}\">{u.name}<\/li>\n      ))}\n    <\/ul>\n  );\n}\n\nconst UserPage = () => {\n  const [userData, setUserData] = useState<user>([]);\n\n  const filters = {\n    role: \"admin\",\n    active: true,\n  };\n\n  return <userlist filters=\"{filters}\" onload=\"{setUserData}\" users=\"{userData}\"\/>;\n};\n\nexport default UserPage;\n<\/user><\/code><\/pre>\n<p>\u06a9\u06c1 <code>UserList<\/code> \u062c\u0628 \u0646\u0635\u0628 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u062c\u0632\u0648 \u0635\u0627\u0631\u0641 \u06a9\u0648 \u0645\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>filters<\/code> \u0627\u0648\u0631 <code>onLoad<\/code> \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u06d4<\/p>\n<p>\u0645\u0633\u0626\u0644\u06c1 \u06cc\u06c1\u0627\u06ba \u06c1\u06d2\u06d4 <code>filters<\/code> \u06a9\u0627 \u0627\u0639\u062a\u0631\u0627\u0636 <code>UserPage<\/code> \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u062c\u0628 \u0628\u06be\u06cc \u0631\u06cc\u0646\u0688\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u0642\u062f\u0631\u06cc\u06ba \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06cc \u0646\u0638\u0631 \u0622\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u062a\u0628 \u0628\u06be\u06cc \u0648\u06c1 \u0646\u0626\u06d2 \u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a \u06c1\u06cc\u06ba \u062c\u0628 \u0628\u06be\u06cc \u0648\u06c1 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u06cc\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>UserList<\/code> \u0627\u0633\u06d2 \u06c1\u0631 \u0628\u0627\u0631 \u0627\u06cc\u06a9 \u0646\u0626\u06cc \u0642\u062f\u0631 \u0633\u0645\u062c\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u06d2 <code>useEffect<\/code> \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0627\u0646\u062d\u0635\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/umang.pk\/wp-content\/uploads\/2026\/06\/1781739980_309_React-\u0645\u06cc\u06ba-\u06cc\u0648\u0632-\u06a9\u0627\u0644-\u0628\u06cc\u06a9-\u0627\u0648\u0631-\u06cc\u0648\u0632-\u0645\u06cc\u0645\u0648-\u06a9\u06d2-\u063a\u0644\u0637.gif\" alt=\"\u0628\u0631\u0627\u0624\u0632\u0631 \u0644\u0627\u0645\u062d\u062f\u0648\u062f \u0644\u0627\u06af \u062f\u06a9\u06be\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u06d4 \" style=\"display:block;margin:0 auto\" width=\"800\" height=\"477\" loading=\"lazy\" USER title=\"\"><\/p>\n<p>\u0631\u06cc\u067e\u0646\u06af <code>filters<\/code> \u06a9\u0648 <code>useMemo<\/code> \u06cc\u06c1 \u0644\u0648\u067e \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0635\u0644 \u0645\u0633\u0626\u0644\u06c1 \u06a9\u0648 \u06cc\u0627\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2. <code>useMemo<\/code> \u06c1\u0645 \u0644\u0627\u0645\u062d\u062f\u0648\u062f \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u06a9\u0648 \u062d\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u0628\u06c1\u062a\u0631 \u062d\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u0627 \u0622\u067e\u0634\u0646 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0646\u062d\u0635\u0627\u0631\u06cc \u0633\u0631\u0646\u06cc \u06a9\u06cc \u0642\u062f\u06cc\u0645 \u0642\u0633\u0645 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u0633\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u06d2 <code>useEffect<\/code> \u06c1\u0631 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u0627\u0633\u06d2 \u067e\u0691\u06be\u06cc\u06ba \u06af\u06d2\u060c \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u062e\u062a\u0644\u0641 \u062d\u0648\u0627\u0644\u06c1 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627\u06d4 <code>filter<\/code> \u0633\u06c1\u0627\u0631\u06d2 \u0642\u062f\u06cc\u0645 \u0639\u0646\u0627\u0635\u0631 \u06a9\u0627 \u0642\u062f\u0631 \u0633\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">function UserList({ filters, onLoad, users }: UserListProps) {\n  console.count(\"__ USER LIST __\");\n\n  useEffect(() => {\n    fetchUsers(filters).then((data) => {\n      onLoad(data);\n    });\n  }, [filters.active, filters.role]); \/\/ primitives compare by value, not reference\n\n  return (\n    <ul>\n      {users.map((u) => (\n        <li key=\"{u.id}\">{u.name}<\/li>\n      ))}\n    <\/ul>\n  );\n}\n<\/code><\/pre>\n<p>\u062f\u0648\u0633\u0631\u0627 \u0622\u067e\u0634\u0646 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062c\u0632\u0648 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u06cc \u062c\u0627\u0626\u06d2 \u062a\u0627\u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u0633 \u06a9\u0627 \u0645\u0633\u062a\u062d\u06a9\u0645 \u062d\u0648\u0627\u0644\u06c1 \u06c1\u0648\u06d4<\/p>\n<pre><code class=\"language-typescript\">const filters = {\n  role: \"admin\",\n  active: true,\n};\n\nconst UserPage = () => {\n  const [userData, setUserData] = useState<user>([]);\n\n  return <userlist filters=\"{filters}\" onload=\"{setUserData}\" users=\"{userData}\"\/>;\n};\n<\/user><\/code><\/pre>\n<p>\u062a\u06cc\u0633\u0631\u0627 \u062d\u0644 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u062d\u0627\u0644\u062a \u0645\u06cc\u06ba \u0645\u062d\u0641\u0648\u0638 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u0627\u06af\u0631 \u0634\u06d2 \u0645\u062a\u062d\u0631\u06a9 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-typescript\">const UserPage = () => {\n  const [userData, setUserData] = useState<user>([]);\n  const [filters, setFilters] = useState({\n    role: \"admin\",\n    active: true,\n  });\n\n  return <userlist filters=\"{filters}\" onload=\"{setUserData}\" users=\"{userData}\"\/>;\n};\n<\/user><\/code><\/pre>\n<h2 id=\"heading-when-to-use-usecallback-and-usememo\">\u06a9\u0628 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code><\/h2>\n<p>\u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u06a9\u0627 \u0645\u0642\u0635\u062f \u0622\u067e \u06a9\u0648 \u06cc\u06c1 \u0628\u062a\u0627\u0646\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0627\u0646 \u06c1\u06a9\u0633 \u06a9\u0648 \u06a9\u0628\u06be\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u062d\u0642\u06cc\u0642\u06cc \u0632\u0646\u062f\u06af\u06cc \u06a9\u06d2 \u062d\u0627\u0644\u0627\u062a \u06c1\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u06cc\u06c1 \u06c1\u06a9\u0633 \u0686\u0645\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-measure-before-you-optimize\">\u0627\u0635\u0644\u0627\u062d \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u067e\u06cc\u0645\u0627\u0626\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0627\u0635\u0644\u0627\u062d \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u06af\u06d2 \u0628\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 <code>useCallback<\/code>\u060c <code>useMemo,<\/code> \u0645\u062a\u0628\u0627\u062f\u0644 \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u06af\u0631 \u0622\u067e \u06a9\u0633\u06cc \u062c\u0632\u0648 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06d2 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u06a9\u0648\u0688 \u06a9\u0648 \u0628\u06c1\u062a\u0631 \u0628\u0646\u0627\u0646\u0627 \u062c\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u0633\u06cc \u06a9\u0648 \u0641\u0627\u0626\u062f\u06c1 \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u062a\u0627\u06d4<\/p>\n<p>React DevTools \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u067e\u0631\u0648\u0641\u0627\u0626\u0644\u0631 \u0679\u06cc\u0628 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0633\u06cc\u0634\u0646 \u06a9\u0648 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u06cc\u0627 \u062c\u0627 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u06a9\u062a\u0646\u06cc \u0628\u0627\u0631\u060c \u0627\u0648\u0631 \u06c1\u0631 \u0631\u06cc\u0646\u0688\u0631 \u0645\u06cc\u06ba \u06a9\u062a\u0646\u0627 \u0648\u0642\u062a \u0644\u06af\u062a\u0627 \u06c1\u06d2\u06d4 React \u0688\u0648\u06cc\u0644\u067e\u0631 \u0679\u0648\u0644\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba &#8211; \u0645\u062b\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u0636\u0627\u062d\u062a \u067e\u0691\u06be\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0648\u06cc\u0688\u06cc\u0648 \u06a9\u06d2 \u067e\u0631\u0633\u062a\u0627\u0631 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0628\u06cc\u0646 \u06a9\u0648 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u062a\u0644\u0627\u0634 \u06a9\u0631\u0646\u06d2 \u0627\u0648\u0631 \u0627\u0646 \u06a9\u0648 \u0679\u06be\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 React \u067e\u0631\u0648\u0641\u0627\u0626\u0644\u0631 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0645\u0638\u0627\u06c1\u0631\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-stabilize-references-for-reactmemo-children\">\u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a \u06a9\u0648 \u0645\u0633\u062a\u062d\u06a9\u0645 \u06a9\u0631\u06cc\u06ba\u06d4 <code>React.memo<\/code> \u0628\u0686\u06d2<\/h3>\n<p><code>React.memo<\/code>    \u0627\u06af\u0631 \u067e\u0631\u067e\u0633 \u062a\u0628\u062f\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0626\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u062c\u0632\u0648 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u067e\u06cc\u0634 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u0627\u06c1\u0645\u060c \u0627\u06af\u0631 \u0622\u067e \u06a9\u0633\u06cc \u0641\u0646\u06a9\u0634\u0646 \u06cc\u0627 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u067e\u0631\u0648\u067e \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0627\u0633 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0628\u0686\u06d2 \u06a9\u0648 \u06c1\u0631 \u067e\u06cc\u0631\u0646\u0679 \u0631\u06cc\u0646\u0688\u0631 \u067e\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u0631\u06c1\u06d2 \u06af\u0627 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u0627\u0648\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06a9\u0648 \u06c1\u0631 \u0628\u0627\u0631 \u0627\u06cc\u06a9 \u0646\u0626\u06d2 \u062d\u0648\u0627\u0644\u06c1 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u0627\u0633\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u0648\u0642\u062a \u06c1\u06d2\u06d4 <code>useCallback<\/code> \u06cc\u0627 <code>useMemo<\/code>:<\/p>\n<pre><code class=\"language-typescript\">const Child = React.memo(({ onClick }: { onClick: () => void }) => {\n  console.log(\"Child rendered\");\n  return <button onclick=\"{onClick}\">Click me<\/button>;\n});\n\nfunction Parent() {\n  const [count, setCount] = useState(0);\n\n  const handleClick = useCallback(() => {\n    console.log(\"clicked\");\n  }, []);\n\n  return (\n    <>\n      <button onclick=\"{()\"> setCount((c) => c + 1)}>Increment: {count}<\/button>\n      <child onclick=\"{handleClick}\"\/>\n    >\n  );\n}\n<\/code><\/pre>\n<p>\u0628\u063a\u06cc\u0631 <code>useCallback<\/code>\u060c <code>Child<\/code> \u06c1\u0631 \u0628\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 <code>count<\/code> \u0686\u0627\u06c1\u06d2 \u0648\u06c1 \u0628\u062f\u0644 \u062c\u0627\u0626\u06d2\u06d4 <code>handleClick<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 <code>count<\/code>. \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>useCallback<\/code>\u0641\u0646\u06a9\u0634\u0646 \u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a \u0645\u0633\u062a\u062d\u06a9\u0645 \u0631\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0627\u06a9\u062b\u0631 \u0628\u06c1\u062a\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>useCallback<\/code> \u0627\u0648\u0631 <code>React.memo<\/code> \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0644\u06cc\u06a9\u0646 <code>React.memo<\/code> \u0627\u06af\u0631 \u067e\u0631\u067e\u0633 \u0642\u062f\u06cc\u0645 \u06cc\u0627 \u0645\u0633\u062a\u062d\u06a9\u0645 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0648\u06c1 \u0627\u067e\u0646\u06d2 \u0622\u067e \u0645\u06cc\u06ba \u0645\u0641\u06cc\u062f \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0648\u0631 <code>useCallback<\/code> \u0628\u0627\u06c1\u0631 \u0628\u06be\u06cc \u0645\u0641\u06cc\u062f \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>React.memo<\/code>\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0627\u0644 \u0628\u06cc\u06a9\u0633 \u06a9\u0648 \u0627\u06cc\u0641\u06cc\u06a9\u0679\u0633\u060c \u06a9\u0633\u0679\u0645 \u06c1\u06a9\u0633\u060c \u06cc\u0627 \u062a\u06be\u0631\u0688 \u067e\u0627\u0631\u0679\u06cc \u0627\u062c\u0632\u0627\u0621 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a\u06d4<\/p>\n<h2 id=\"heading-conclusion\">\u0646\u062a\u06cc\u062c\u06c1<\/h2>\n<p><code>useCallback<\/code>    \u0627\u0648\u0631 <code>useMemo<\/code> \u06cc\u06c1 \u0646\u0648\u0679 \u0644\u06cc\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0645\u0641\u06cc\u062f \u0679\u0648\u0644 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0645\u0641\u062a \u067e\u0631\u0641\u0627\u0631\u0645\u0646\u0633 \u0627\u067e \u06af\u0631\u06cc\u0688 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06c1\u0631 \u06a9\u0627\u0644 \u06c1\u0631 \u0631\u06cc\u0646\u0688\u0631 \u0645\u06cc\u06ba \u0645\u06cc\u0645\u0648\u0631\u06cc \u0627\u0648\u0648\u0631 \u06c1\u06cc\u0688 \u0627\u0648\u0631 \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06c1\u0645\u06cc\u0634\u06c1 \u0627\u067e\u0646\u06d2 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba \u062a\u0627\u06a9\u06c1 \u0628\u06c1\u062a \u06a9\u0645 \u0627\u0635\u0644\u0627\u062d \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06d4 \u0631\u06cc\u0627\u0633\u062a \u0627\u0648\u0631 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0627\u0633 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u062c\u0632\u0627\u0621 \u06a9\u06d2 \u062c\u062a\u0646\u0627 \u0645\u0645\u06a9\u0646 \u06c1\u0648 \u0642\u0631\u06cc\u0628 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>useCallback<\/code> \u0627\u0648\u0631 <code>useMemo<\/code> \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be <code>React.memo<\/code> \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u06a9\u06c1 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u0648\u0627\u0642\u0639\u06cc \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0627\u06af\u0631 \u0622\u067e \u0646\u06d2 React \u0627\u06cc\u06a9\u0648 \u0633\u0633\u0679\u0645 \u0645\u06cc\u06ba \u06a9\u0627\u0641\u06cc \u0648\u0642\u062a \u06af\u0632\u0627\u0631\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u0646\u06d2 \u0634\u0627\u06cc\u062f \u06a9\u0648\u0688 \u0628\u06cc\u0633\u0632 \u062f\u06cc\u06a9\u06be\u06d2 \u06c1\u0648\u06ba \u06af\u06d2 \u062c\u06c1\u0627\u06ba \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0627\u0633 \u0637\u0631\u062d \u0644\u067e\u06cc\u0679 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: useCallback \u062d\u0633\u0627\u0628\u06cc \u0642\u062f\u0631 \u0627\u0633 \u0637\u0631\u062d \u0644\u067e\u06cc\u0679\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2: useMemo. \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 &quot;\u0646\u0648\u0679 \u0644\u06cc\u0646\u06d2 \u0633\u06d2 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u0628\u06c1\u062a\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4&#8221; \u062a\u0627\u06c1\u0645\u060c \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0645\u0639\u0627\u0645\u0644\u0627\u062a [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":25491,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-25490","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/25490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/comments?post=25490"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/25490\/revisions"}],"predecessor-version":[{"id":25492,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/posts\/25490\/revisions\/25492"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media\/25491"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/media?parent=25490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/categories?post=25490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/en_us\/wp-json\/wp\/v2\/tags?post=25490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}