use - This feature is available in the latest Canary

Canary

ה-use Hook זמין כרגע רק בערוצים הקנריים והניסיוניים של React. למידע נוסף על ערוצי ההפצה של React כאן.

use הוא React Hook המאפשר לך לקרוא את הערך של משאב כמו הבטחה או הקשר.

const value = use(resource);

הפניה

use(resource)

התקשר ל-use ברכיב שלך כדי לקרוא את הערך של משאב כמו הבטחה או הקשר.

import { use } from 'react';

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...

בניגוד לכל React Hooks האחרים, ניתן לקרוא ל-use בתוך לולאות ו-stateמנטים מותנים כמו if. כמו React Hooks אחרים, הפונקציה שקוראת ל-use חייבת להיות Component או Hook.

כאשר קוראים עם הבטחה, ה-use Hook משתלב עם Suspense ו-גבולות שגיאה. הרכיב הקורא ל-use משהה בזמן שההבטחה שהועברה ל-use ממתינה. אם הרכיב שקורא ל-use עטוף בגבול Suspense, ה-fallback יוצג. לאחר פתרון ההבטחה, ההחלפה Suspense מוחלפת ברכיבים שניתנו באמצעות הנתונים המוחזרים על ידי use Hook. אם ההבטחה שהועברה ל-use תדחה, תוצג החזרה של גבול השגיאה הקרוב ביותר.

ראה דוגמאות נוספות למטה.

פרמטרים

  • resource: זהו המקור של הנתונים שמהם אתה רוצה לקרוא ערך. משאב יכול להיות הבטחה או הקשר.

מחזירה

ה-use Hook מחזיר את הערך שנקרא מהמשאב כמו הערך שנפתר של הבטחה או הקשר.

אזהרות

  • יש לקרוא ל-use Hook בתוך רכיב או Hook.
  • בעת שליפת נתונים ב-רכיב שרת, העדיפו async וawait על פני use. async וawait קולטים רינדור מהנקודה שבה await הופעל, ואילו use מעבד מחדש את הרכיב לאחר פתרון הנתונים.
  • העדיפו יצירת הבטחות ב-Server Components והעברתם ל-Client Components על פני יצירת הבטחות ברכיבי לקוח. הבטחות שנוצרו ברכיבי לקוח נוצרות מחדש בכל עיבוד. הבטחות המועברות מרכיב שרת לרכיב לקוח יציבות בעיבודים חוזרים. ראה דוגמה זו.

שימוש

קריאה בהקשר עם use

כאשר הקשר מועבר ל-use, זה עובד בדומה ל-useContext. בעוד ש-useContext חייב להיקרא ברמה העליונה של הרכיב שלך, ניתן לקרוא ל-use בתוך תנאים כמו if ולולאות כמו for. use מועדף על פני useContext מכיוון שuse הוא גמיש יותר.

import { use } from 'react';

function Button() {
const theme = use(ThemeContext);
// ...

use מחזירה את ערך ההקשר עבור context שעברת. כדי לקבוע את ערך ההקשר, React מחפש בעץ הרכיבים ומוצא את ספק ההקשר הקרוב ביותר לעיל עבור ההקשר המסוים הזה.

כדי להעביר הקשר ל-Button, עטוף אותו או אחד ממרכיבי האב שלו לספק ההקשר המתאים.

function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}

function Form() {
// ... renders buttons inside ...
}

זה לא משנה כמה שכבות של רכיבים יש בין הספק ל-Button. כאשר Button בכל מקום בתוך Form קורא use(ThemeContext), הוא יקבל "dark" כערך.

בניגוד ל-useContext, use ניתן לקרוא בתנאים וללולאות כמו if.

function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}

use is called from inside a if statement, allowing you to conditionally read values from a Context.

Pitfall

כמו useContext, use(context) תמיד מחפש את ספק ההקשר הקרוב ביותר מעל הרכיב שקורא לו. הוא מחפש כלפי מעלה ולא מחשיב ספקי הקשר ברכיב שממנו אתה קורא ל-use(context).

import { createContext, use } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

function Form() {
  return (
    <Panel title="Welcome">
      <Button show={true}>Sign up</Button>
      <Button show={false}>Log in</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = use(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ show, children }) {
  if (show) {
    const theme = use(ThemeContext);
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {children}
      </button>
    );
  }
  return false
}

הזרמת נתונים מהשרת ללקוח

ניתן להזרים נתונים מהשרת ללקוח על ידי העברת הבטחה כאביזר מרכיב שרת לרכיב לקוח.

import { fetchMessage } from './lib.js';
import { Message } from './message.js';

export default function App() {
const messagePromise = fetchMessage();
return (
<Suspense fallback={<p>waiting for message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

רכיב לקוח לאחר מכן לוקח את ההבטחה שקיבל כפרופסיה ומעביר אותה ל-use Hook. זה מאפשר לרכיב לקוח לקרוא את הערך מההבטחה שנוצרה בתחילה על ידי רכיב השרת.

// message.js
'use client';

import { use } from 'react';

export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}

מכיוון שuse Message עטוף ב-Suspense, ההחלפה תוצג עד לפתרון ההבטחה. כאשר ההבטחה תיפתר, הערך ייקרא על ידי use Hook והרכיב Message יחליף את ה-fallback Suspense.

"use client";

import { use, Suspense } from "react";

function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Here is the message: {messageContent}</p>;
}

export function MessageContainer({ messagePromise }) {
  return (
    <Suspense fallback={<p>⌛Downloading message...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  );
}

Note

בעת העברת הבטחה מרכיב שרת לרכיב לקוח, הערך שנפתר שלה חייב להיות ניתן לסידרה כדי לעבור בין שרת ללקוח. סוגי נתונים כמו פונקציות אינם ניתנים לסידרה ואינם יכולים להיות הערך הפתור של הבטחה כזו.

Deep Dive

האם עלי לפתור הבטחה ברכיב שרת או לקוח?

ניתן להעביר הבטחה מרכיב שרת לרכיב לקוח ולפתור אותו ברכיב הלקוח עם ה-use Hook. אתה יכול גם לפתור את ההבטחה ברכיב שרת עם await ולהעביר את הנתונים הנדרשים לרכיב הלקוח בתור אביזר.

export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}

אבל שימוש ב-await ב-רכיב שרת יחסום את העיבוד שלו עד לסיום ה-await statement. העברת הבטחה מרכיב שרת לרכיב לקוח מונעת מההבטחה לחסום את העיבוד של רכיב השרת.

התמודדות עם הבטחות שנדחו

במקרים מסוימים הבטחה שהועברה ל-use עלולה להידחות. אתה יכול לטפל בהבטחות שנדחו על ידי:

  1. הצגת שגיאה ל-users עם גבול שגיאה.
  2. מתן ערך חלופי עם Promise.catch

Pitfall

לא ניתן לקרוא ל-use בבלוק טרי-catch. במקום חסימת try-catch עטפו את הרכיב שלך ב-Error Boundary, או ספק ערך חלופי ל-use בשיטת .catch של ההבטחה.

הצגת שגיאה ל-users עם גבול שגיאה

אם תרצה להציג שגיאה ל-users שלך כאשר הבטחה נדחתה, אתה יכול use גבול שגיאה. כדי use גבול שגיאה, עטוף את הרכיב שבו אתה קורא את use Hook בגבול שגיאה. אם ההבטחה שהועברה ל-use נדחתה, החזרה לגבול השגיאה תוצג.

"use client";

import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
      <Suspense fallback={<p>⌛Downloading message...</p>}>
        <Message messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Message({ messagePromise }) {
  const content = use(messagePromise);
  return <p>Here is the message: {content}</p>;
}

מתן ערך חלופי עם Promise.catch

אם ברצונך לספק ערך חלופי כאשר ההבטחה שהועברה ל-use נדחתה, תוכל use שיטת catch) של ההבטחה.

import { Message } from './message.js';

export default function App() {
const messagePromise = new Promise((resolve, reject) => {
reject();
}).catch(() => {
return "no new message found.";
});

return (
<Suspense fallback={<p>waiting for message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

כדי use שיטת catch של ה-Promise, קרא catch באובייקט ה-Promise. catch לוקח ארגומנט בודד: פונקציה שלוקחת הודעת שגיאה כארגומנט. כל מה שיוחזר על ידי הפונקציה המועברת ל-catch יהיה used כערך שנפתר של ההבטחה.


פתרון בעיות

“Suspense חריג: זו לא שגיאה אמיתית!”

או שאתה קורא ל-use מחוץ לרכיב React או פונקציה Hook, או קורא ל-use בלוק של try-catch. אם אתה קורא use בתוך בלוק try-catch, עטוף את הרכיב שלך בגבול שגיאה, או התקשר ל-catch של ההבטחה כדי לתפוס את השגיאה ולפתור את ההבטחה עם ערך אחר. ראה דוגמאות אלה.

אם אתה קורא ל-use מחוץ לרכיב React או פונקציה Hook, העבר את הקריאה use לרכיב React או פונקציה Hook.

function MessageComponent({messagePromise}) {
function download() {
// ❌ the function calling `use` is not a Component or Hook
const message = use(messagePromise);
// ...

במקום זאת, קרא ל-use מחוץ לכל סגירת רכיבים, כאשר הפונקציה שקוראת ל-use היא רכיב או Hook.

function MessageComponent({messagePromise}) {
// ✅ `use` is being called from a component.
const message = use(messagePromise);
// ...