useImperativeHandle

useImperativeHandle הוא React Hook שמאפשר להתאים אישית את ה-handle שנחשף כ-ref.

useImperativeHandle(ref, createHandle, dependencies?)

הפניה

useImperativeHandle(ref, createHandle, dependencies?)

קראו ל-useImperativeHandle ברמה העליונה של הקומפוננטה כדי להתאים אישית את ה-Ref handle שהיא חושפת:

import { forwardRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);
// ...

עוד דוגמאות נוספות.

פרמטרים

  • ref: ה-ref קיבלתם כארגומנט השני מתוך forwardRef render function.

  • createHandle: פונקציה שלא מקבלת ארגומנטים ומחזירה את ref handle שתרצו לחשוף. ה-handle יכול הזה להיות מכל סוג. בדרך כלל תחזירו אובייקט עם המתודות שתרצו לחשוף.

  • אופציונלי dependencies: רשימה של כל הערכים הריאקטיביים שמופנים בתוך קוד ה-createHandle. ערכים ריאקטיביים כוללים props, state וכל המשתנים והפונקציות שמוגדרים באופן עצמאי בתוך גוף הקומפוננטה. אם ה-linter שלכם מוגדר ל-React, הוא יוודא שכל ערך ריאקטיבי מצוין נכון כ-dependency. רשימת התלות חייבת להיות מספר פריטים קבועים וכתב מוטבע כמו [dep1, dep2, dep3]. React תשווה כל התלות לערך קודמת שלו באמצעות Object.is. אם מחדש גרם לשינוי ב-dependency, או אם השמטתם את הארגומנט הזה, פונקציית createHandle תרוץ מחדש, וה-handle החדש שייווצר יוקצה ל-ref.

מחזירה

useImperativeHandle מחזיר undefined.


שימוש

חשיפת ref handle מותאם לקומפוננטת ההורה

כברירת מחדל, קומפונטות לא חושפות את ה-DOM צמתים שלהן לקומפוננטות הורה. למשל, אם אתם רוצים שלקומפונטת ההורה של MyInput תהיה גישה ל-<input> DOM צומת, צריך לבצע הסכמה עם forwardRef:

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});

עם הקוד למעלה, ref L-MyInput יקבל את הצומת <input> DOM. אבל אפשר גם לחשוף ערך מותאם אישית במקום. כדי להתאים את הידית שנחשף, קראו ל-useImperativeHandle ברמה העליונה של הקומפוננטה:

import { forwardRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
useImperativeHandle(ref, () => {
return {
// ... your methods ...
};
}, []);

return <input {...props} />;
});

שימו לב שבקוד למעלה, ה-ref כבר לא מועבר ל-<input>.

לדוגמה, נניח שאתה לא רוצה לחשוף את כל הצומת <input> DOM, אלא רק שתי מתודות: focus ו-scrollIntoView. כדי לעשות זאת, שמרו את ה-DOM האמיתי של הדפדפן ב-ref נפרד. אחר כך השתמשו ב-useImperativeHandle כדי לחשוף את הידית שמכילה רק את המתודות שההורה תוכל לקרוא להן:

import { forwardRef, useRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);

useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);

return <input {...props} ref={inputRef} />;
});

עכשיו, אם קומפוננתת ההורה מקבלת ref ל-MyInput, היא תוכל לקרוא למתודות focus ו-scrollIntoView. עם זאת, לא תהיה גישה מלאה ל-<input> DOM צומת עצמו.

import { useRef } from 'react';
import MyInput from './MyInput.js';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
    // This won't work because the DOM node isn't exposed:
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput placeholder="Enter your name" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}


חשיפת מתודות ציווי משלכם

המתודות שלך חושפים דרך ציווי ידית לא חייבות להתאים בדיוק למתודות DOM. לדוגמה, קומפונטת Post הזו חושפת מתודה בשם scrollAndFocusAddComment דרך ציווי אחיזה. זה יכול ל-Page ההורה לגלול את רשימת התגובות וגם לפקס את שדה הקלט כשהם לוחצים על הכפתור:

import { useRef } from 'react';
import Post from './Post.js';

export default function Page() {
  const postRef = useRef(null);

  function handleClick() {
    postRef.current.scrollAndFocusAddComment();
  }

  return (
    <>
      <button onClick={handleClick}>
        Write a comment
      </button>
      <Post ref={postRef} />
    </>
  );
}

Pitfall

אל תשתמשו ב-refs המשך לנדרש. כדאי להשתמש ב-refs רק להתנהגויות ציווי ניתן לבטא כ-props: למשל שלא גלילה ל-node, פוקוס ל-node, הפעלת אנימציה, בחירת טקסט, וכן הלאה.

אם אפשר לבטא משהו כ-prop, לא כדאי להשתמש ב-ref. לדוגמה, במקום לחשוף imperative handle כמו { open, close } מתוך קומפוננטת Modal, עדיף לקבל isOpen כ-prop כמו <Modal isOpen={isOpen} />. אפקטים יכולים לעזור לחשוף התנהגויות ציווי דרך props.