هوک useNavigation

نگاهی به هوک‌های useNavigation : React

در این سری از مقالات آموزش React برای افراد مبتدی، نگاهی ساده به کارکرد useNavigation خواهیم داشت. قبل از هر چیز یادآوری می‌کنیم که این هوک هم در پروژه‌های React Native و هم در پروژه‌های React که از React Router استفاده می‌کنند، قابل دسترسی است.

اطلاعات اولیه: React Router چیست؟

در مواردی که پروژه تک صفحه‌ای React شما به پیمایش صفحه یا روتینگ (Routing) نیاز دارد، چیزی به نام client-side-routing را به خدمت می‌گیرد. در واقع در React، راه حلی که برای روتینگ سمت کلاینت درنظر گرفته شده است، React Router نام گرفته است.

پیشنهاد مقاله: شروع آموزش برنامه‌نویسی

React Router، این امکان را به برنامه شما می‌دهد که بدون این که به درخواست یا بارگزاری مجدد صفحه از سمت سرور داشته باشد، کل صفحات موجود در URL را پیمایش کند و همین، رندرینگ UI برنامه شما را سریع‌تر و پویاتر خواهد کرد.

هوک useNavigation چه کار می‌کند؟

useNavigation، هوکیست که در روتر React قابل دسترسی است.

این هوک، طبق گفته اسناد رسمی React، تمام اطلاعات موردنیاز شما برای پیمایش یک صفحه را در اختیار شما قرار می‌دهد. اطلاعاتی نظیر این موارد:

  • شاخص‌های گلوبال بارگزاری
  • غیرفعال‌سازی فرم‌ها در زمانی که تغییراتی در حال وقوع است.
  • افزودن اندیکاتورهای اشغال (Busy) به سابمیت دکمه‌ها
  • نمایش رکورد جدیدی که در سمت سرور در حال ساخت است.
  • نمایش وضعیت جدید یک رکورد در حین به روزرسانی آن

اما می‌خواهیم به طور خاص روی کاربرد ساده هوک useNavigation تمرکز کنیم.

import { useNavigation } from "react-router-dom";

function App() {
  const navigation = useNavigation();
}

نکته: یادتان باشد که useNavigation فقط باید همراه با روترهای داده مورد استفاده قرار گیرد.

در کد بالا، متغیر navigation می‌تواند موارد زیر را بازگرداند:

  • navigation.state : این استیت می‌تواند idle (بی کار) ، submitting (در حال تحویل داده) یا loading (در حال بارگزاری) باشد.
  • navigation.location : لینک صفحه‌ای که کاربر، می‌خواهد به آن صفحه برود.
  • navigation.formData : داده‌های سابمیشن فورم
  • navigation.formAction: آدرس url که فورم به آن تحویل داده خواهد شد.
  • navigation.formMethod : یکی از روش‌های PATCH، PUT ، POST یا DELETE را در خود دارد.

یک مثال ساده

حال می‌خواهیم مثال ساده‌ای از کاربرد use.Navigation را با هم مشاهده کنیم. در React App، یک لیست وظایف (Todo List) را رندر کرده‌ایم که داخل آن یک فرم ورود اطلاعات برای درج یک وظیفه جدید وجود دارد. چیزی شبیه این:

react app

در ادامه، کد کامپوننت App را مشاهده می‌کنید:

export function App() {
  let navigation = useNavigation();
  let formRef = useRef(null);
  let [isAdding, setIsAdding] = useState(false);

  useEffect(() => {
    if (navigation.formData?.get('action') === 'add') {
      setIsAdding(true);
    } else if (navigation.state === 'idle') {
      setIsAdding(false);
      formRef.current?.reset();
    }
  }, [navigation]);

  return (
    <>
      <h2>Todos</h2>
      <p>
        Click on a todo item to navigate
        to the /todo/:id route.
      </p>
      <ul>
        {Object.entries(todos).map(([id, todo]) => (
          <li key={id}>
             <Link to={`/todo/${id}`}>{todo}</Link>
          </li>
        ))}
      </ul>
      <Form method="post" ref={formRef}>
      <input type="hidden" name="action" value="add" />
        <input name="todo"></input>
        <button type="submit" disabled={isAdding}>
          {isAdding ? 'Adding...' : 'Add'}
        </button>
      </Form>
    </>
  )
}

همان‌طور که در کد بالا می‌بینید، در حین سابمیت فرم از هوک useNavigation برای غیر فعال کردن دکمه submit و نمایش عبارت …Adding روی دکمه استفاده شده است.

همزمان، وقتی آیتم جدیدی به لیست اضافه می‌شود، این صفحه به طور اتوماتیک به یک روت داینامیک با نام todo/:id هدایت می‌شود. می‌توانیم از هوک useParams برای روتینگ داینامیک استفاده کنیم و برنامه را به کامپوننت Todo هدایت کنیم.

شکل زیر، محتوای کامپوننت Todo را نشان می‌دهد. Todo/0 نشان دهنده اولین آیتم لیست است، Todo/1 ، دومین آیتم و همین‌طور الی آخر .

کد این کامپوننت از قرار زیر است:

export function Todo() {
  let params = useParams();
  return (
    <>
      <h2>You are now at todo/{params.id} route</h2>
      <p>id: {params.id}</p>
      <p>todo: {todos[params.id]}</p>
    </>
  )
}

حال در فایل main.jsx روتر خود را تنظیم می‌کنیم. این فایل، تمام مسیرهایی که به پیمایش آن‌ها نیاز داریم، مشخص می‌کند.

import {
  createBrowserRouter,
  createRoutesFromElements,
  Route,
  RouterProvider,
} from "react-router-dom";


let router = createBrowserRouter( createRoutesFromElements(
  <>
  <Route path="/" action={todosAction} element={<App />} />
  <Route path="/todo/:id" element={<Todo />} />
  </>
  ) )

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
     <RouterProvider router={router} />
  </React.StrictMode>
);

در نهایت، todoAction ما مسئول افزودن یک آیتم جدید به لیست todo و هدایت آن به سمت روتینگ داینامیک ما خواهد بود:

export async function todosAction({ request }) {
  let formData = await request.formData();
  let todo = formData.get('todo');
  if (typeof todo === 'string') {
    addTodo(todo);
  }

  await new Promise((r) => setTimeout(r, 500)); //just to show submitting state
  return new Response(null, {
    status: 302,
    headers: { Location: `/todo/${Object.keys(todos).length-1}`},
  });
}

نتیجه

حال می‌توانیم ببینیم که هنگام سابمیت فرم اتفاقات زیر رخ می‌دهد:

سابمیت ما برابر است با navigate.state

navigation.state حاوی کلیدهای action و todo است.

مقدار todo به  لیست اضافه شده است و صفحه به todo/:id هدایت شده است.

در این مقاله با هوک useNavigatıon  آشنا شدیم و کاربردهای آن را شناختیم. همچنین، نحوه پیاده‌سازی هوک useNavigation را مشاهده کردیم. امیدواریم این مقاله، به درک بهتر نحوه عملکرد هوک useNavigation کمک کرده باشد.

از این که ما را تا پایان مقاله، همراهی کردید، سپاسگزاریم. لطفاً اگر این مقاله را مفید یافته‌اید، آن را با دوستان خود به اشتراک بگذارید و در بخش کامنت، ما را از نظرات مشوقانه خود بهره‌مند سازید و اگر سؤالی دارید، با ما به اشتراک بگذارید تا با هم در مورد رسیدن به پاسخ مناسب، تلاش کنیم.

ثبت ديدگاه