כיצד לשדרג ל-React 18
8 במרץ 2022 מאת ריק הנלון
כפי שנו ב-release post, React 18 הצגת חלק תכלית המופעלות על ידי המעבד החדש שלנו, עם אסטרטגית אימוץ הדרגתית עבור יישומים קיימים. בפוסט זה נדריך אותך בשדרוג ל-React 18.
אנא דווח על בעיות כלשהן שנתקלת בה בעת השדרוג ל-React 18.
התקנת
כדי להתקין את הגרסה האחרונה של React:
npm install react react-domאו אם אתה משתמש בחוט:
yarn add react react-domעדכונים לעיבוד לקוח APIs
כאשר תתקין לראשונה את React 18, תראה אזהרה במסוף:
React 18 מציג שורש חדש API הספק ארגונומיה טובה יותר לניהול שורשים. השורש החדש API יכול גם את המעבד החדש, המאפשר לך להצטרף לפתרון.
// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);
// After
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App tab="home" />);שינינו גם את unmountComponentAtNode ל-root.unmount:
// Before
unmountComponentAtNode(container);
// After
root.unmount();הסרנו גם את ההתקשרות חזרה מעיבוד, מה שבדרך כלל אין לו את התוצאה בעת שימוש ב-Suspense:
// Before
const container = document.getElementById('app');
render(<App tab="home" />, container, () => {
console.log('rendered');
});
// After
function AppWithCallbackAfterRender() {
useEffect(() => {
console.log('rendered');
});
return <App tab="home" />
}
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<AppWithCallbackAfterRender />);לבסוף, אם האפליקציה שלך use של עיבוד בצד השרת עם הידרציה, שדרג את hydrate ל-hydrateRoot:
// Before
import { hydrate } from 'react-dom';
const container = document.getElementById('app');
hydrate(<App tab="home" />, container);
// After
import { hydrateRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = hydrateRoot(container, <App tab="home" />);
// Unlike with createRoot, you don't need a separate root.render() call here.למידע נוסף, עיין בדיון בקבוצת העבודה כאן.
עדכונים לעיבוד שרת APIs
במהדורה זו, אנו משפצים את ה-react-dom/server APIs כדי שלנו לתמוך באופן מלא ב-Suspense בשרת וב- Streaming SSR. כחלק משינויים אלה, אנו מוציאים משימוש את הזרמת Node API הישנה, שיינה תומכת בהזרמת Suspense מצטברת בשרת.
שימוש ב-API הזה יזהיר עכשיו:
renderToNodeStream: הוצא שימוש ⛔️️
במקום זאת, עבור סטרימינג בסביבות Node, use:
renderToPipeableStream: חדש ✨
אנו גם מציגים API חדש לתמיכה בהזרמת SSR עם Suspense עבור סביבות זמן ריצה קצה מודרניות, בין עובדי Deno ו-Cloudflare:
renderToReadableStream: חדש ✨
ה-APIs הבאים ימשיכו לעבוד, אך עם תמיכה מוגבלת עבור Suspense:
renderToString: מוגבל ⚠️renderToStaticMarkup: מוגבל ⚠️
לבסוף, API זה ימשיך לעבוד לעיבוד הודעות דואר אלקטרוני:
renderToStaticNodeStream
למידע נוסף על השינויים בעיבוד APIs בשרת, ראה את הפוסט של קבוצת העבודה בנושא שדרוג ל-React 18 בשרת, צלילה עמוקה בארכיטקטורת Suspense SSR החדשה,ה עמוקה ו-[Shaundai Person_2] Suspense SSR](https://github.com/reactwg/react-18/discussions/37), ו-Shaundai Person’s Suspense](https://www.youtube.com/watch?v=pj5N-Khihgc) ב-React Conf 2021.
עדכונים להגדרות TypeScript
אם הפרויקט שלך uses TypeScript, תצטרך לעדכן את התלות @types/react ו@types/react-dom שלך לגרסאות משפטיות. הסוגים החדשים בטוחים יותר ותופסים בעיות שuse יתעלמו מהן על ידי בודק הסוגים. השינוי הבולט ביותר הוא שכעת יש לרשום את הפריט children במפורש בעת הגדרת props, לדוגמה:
interface MyButtonProps {
color: string;
children?: React.ReactNode;
}ראה את React 18 בקשת המשיכה של 18 הקלדות לרשימה מלאה של שינויים סטייליים בלבד. הוא קשור לתיקונים לדוגמה בסוגי ספריות כדי לראות איך להתאים את הקוד שלך.
אם אתה מוצא באג בהקלדות, אנא הגש בעיה ב-repo DefinitelyTyped.
אצווה אוטומטית
React 18 מוסיף שיפורי ביצועים מחוץ לקופסה על ידי ביצוע יותר אצווה כבר מחדל. אצווה היא כאשר React מקבץ עדכוני state מרובים לעיבוד מחדש יחיד לביצועים טובים יותר. לפני React 18, צירפנו רק עדכונים בתוך מטפלי אירועים של React. עדכונים בתוך הבטחות, setTimeout, מטפל אירועים מקוריים או כל אירוע אחר לא צורפו ב-React כברירת מחדל:
// Before React 18 only React events were batched
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will render twice, once for each state update (no batching)
}, 1000);החל מ-React 18 עם createRoot, כל העדכונים יצטברו באופן אוטומטי, לא משנה מהיכן הם מגיעים. משמעות הדבר היא שעדכונים בתוך פסק זמן, הבטחות, רופא אירועים מקוריים או כל אירוע אחר יתבצע באותו אופן כמו עדכונים אירועי React:
// After React 18 updates inside of timeouts, promises,
// native event handlers or any other event are batched.
function handleClick() {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}, 1000);זהו שינוי שובר, אך אנו מצפים שזה יביא לעיבוד פחות עבודה, ביצועים טובים יותר. כדי לבטל את הסכמתך לאיסוף אוטומטי, אתה יכול use flushSync:
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}למידע נוסף, ראה צלילת אצווה עמוקה אוטומטית.
APIs חדשות לספריות
בקבוצת העבודה React 18 עבדנו עם מנהלי ספריות כדי ליצור APIs חדשים הדרושים כדי לתמוך בעיבוד מקביל עבור use מקרים מיוחדים למארז use שלהם אזורים כמו סגנונות וחנויות חיצוניות. כדי לתמוך ב-React 18, אפשר שחלק מהספריות יצטרכו לעבור לאחד מה-APIs הבאים:
useSyncExternalStoreהוא Hook חדש המאפשר לחנויות חיצוניות לתמוך בקריאה במקביל על ידי אילוץ עדכונים לחנות להיות סינכרוניים. API חדש זה מומלץ לכל ספרייה השתלבת עם state חיצונית ל-React. למידע נוסף, עיין בuseSyncExternalStore פוסט סקירה ו-useSyncExternalStore API פרטים.useInsertionEffectהוא Hook חדש המאפשר לספריות CSS-in-JS לטפל בבעיות ביצועים של הזרקת סגנונות בעיבוד. אלא אם כן כבר בנית ספריית CSS-in-JS, אנחנו לא מצפים ממך אי פעם use זה. Hook זה יפעל לאחר שה-DOM יעבור מוטציה, אך לפני אפקטי פריסה קרא את הפריסה החדשה. זה פותר בעיה שכבר קיימת ב-React 17 ומטה, אך חשובה עוד יותר ב-React 18 כי use React תשואות לדפדפן במהלך עיבוד במקביל, מה שנותן לו הזדמנות לחשב מחדש את הפריסה. למידע נוסף, עיין במדריך לשדרוג הספרייה עבור<style>.
React 18 מציג גם APIs חדשות לעיבוד מקביל כמו startTransition, useDeferredValue וuseId, עליהם אנו חולים עוד ב-release post.
עדכונים מצב קפדני
אפשר, נרצה להוסיף תכונה המאפשרת ל-React להוסיף ולהסיר חלקים של ממשק המשתמש תוך שמירה על state. לדוגמה, כאשר user מתרחק מהמסך ובחזרה, React אמור להיות מסוגל להסתכל מיד את המסך הקודם. לשם כך, React יבטל את הטעינה והרכבה מחדש של עצים באמצעות אותו רכיב state כמו קודם.
תכונה זו תעניק ל-React ביצועים טובים יותר מהקופסה, אך מחייבת רכיבים להיות עמידים בפני אפקטים שהוא תקנו והושמדו מספר פעמים. רוב האפקטים יפעלו ללא כל שינוי, אבל חלק מהאפקטים מנחים שהם מוקנים או מושמדים רק פעם אחת.
כדי לעזור לשטח את הבעיות הללו, React 18 מציג בדיקה חדשה לפיתוח בלבד מצב קפדני. הסימון החדש הזה יבטל את הטעינה והרכבה מחדש של כל רכיב, בכל פעם שרכיב נטען בפעם הראשונה, וישחזר את ה-state הקודם בהרכבה השנייה.
לפני השינוי הזה, React היה מעלה את הרכיב ויוצר את האפקטים:
* React mounts the component.
* Layout effects are created.
* Effect effects are created.עם מצב קפדני ב-React 18, React ידמה ביטול הרכבה והרכבה מחדש של הרכיב במצב פיתוח:
* React mounts the component.
* Layout effects are created.
* Effect effects are created.
* React simulates unmounting the component.
* Layout effects are destroyed.
* Effects are destroyed.
* React simulates mounting the component with the previous state.
* Layout effect setup code runs
* Effect setup code runsלמידע נוסף, עיין בפוסטים של קבוצת העבודה עבור הוספת מצב חוזר חוזר ל-StrictMode ו-כיצד לתמוך במצב בר-שימוש חוזר בהשפעות.
הגדרת סביבת הבדיקה שלך
כשתעדכן לראשונה את הבדיקה שלך ל-use createRoot, אפשר שתראה אזהרה זו במסוף הבדיקה שלך:
כדי לתקן זאת, הגדר את globalThis.IS_REACT_ACT_ENVIRONMENT ל-true לפני הפעלת הבדיקה שלך:
// In your test setup file
globalThis.IS_REACT_ACT_ENVIRONMENT = true;מטרת הדגל לומר היא ל-React שהוא פועל בסביבה דמוית בדיקה של יחידה. React ירשום אזהרות מועילות אם תשכח לעטוף עדכון עם act.
אתה יכול גם להגדיר את הדגל ל-false כדי לומר ל-React שאין צורך ב-act. זה יכול להיות useמלא עבור בדיקות מקצה לקצה המדמות סביבת דפדפן מלאה.
בסוף דבר, אנו מצפים שספריות בדיקה יגדירו זאת באופן אוטומטי. לדוגמה, הגרסה הבאה של React ספריית בדיקות כוללת תמיכה מובנית עבור React 18 ללא כל תצורה נוספת.
[רקע נוסף על בדיקת act API ושינויים קשורים] (https://github.com/reactwg/react-18/discussions/102) זמין בקבוצת העבודה.
ביטול התמיכה עבור Internet Explorer
במהדורה זו, React מפסיקה את התמיכה ב-Internet Explorer, הפסקת התמיכה ב-15 ביוני 2022. אנו מבצעים את השינוי הזה עכשיו שuse תכונות חדשות שהוצגו ב-React 18 נבנות שלא באמצעות תכונות דפד כפנויות ב-IE.
אם אתה צריך לתמוך ב-Internet Explorer, אנו ממליצים להישאר עם React 17.
הוצאה שימוש
react-dom:ReactDOM.renderהוצא משימוש. עבודה בו יזהיר ויפעיל את האפליקציה שלך במצב React 17.react-dom:ReactDOM.hydrateהוצא משימוש. עבודה בו יזהיר ויפעיל את האפליקציה שלך במצב React 17.react-dom:ReactDOM.unmountComponentAtNodeהוצא משימוש.react-dom:ReactDOM.renderSubtreeIntoContainerהוצא משימוש.react-dom/server:ReactDOMServer.renderToNodeStreamהוצא משימוש.
שינויים חוזרים אחרים
- תזמון useEffect עקבי: React מסלק באופן אוטומטי סינכרון את הפונקציות האפקט אם עדכון הפעל אירוע קלט נפרד של user קליק קליק או אירוע מקלדת. בעבר, ההתנהגות לא תמיד הייתה צפויה או עקבית.
- שגיאות היד מחמירות: איותר התאמה של הידרציה עקב תוכן טקסט חסר או מי מטופלות עכשיו כשגיאות במקום אזהרות. React לא ינסה עוד “לתקן” צמתים בודדים על ידי הכנסה או מחיקה של צומת לקוח בניסיון להתאים את סימון השרת, ויחזור לעיבוד לקוח עד לגבול
<Suspense>הקרוב ביותר בעץ. זה מבטיח שהעץ המשתלח יהיה עקבי ונמנע מחורים פוטנציאליים של פרטיות ואבטחה שיכולים להיגרם כused על ידי אי התאמה של הידרציה. - Suspense עצים תמיד עקביים: אם רכיב מושהה לפני שהוא מתווסף לגמרי לעץ, React לא יוסיף אותו לעץ ב-state לא שלם או יפעיל את ההשפעות שלו. במקום זאת, React יזרוק את העץ החדש לחלוטין, ימתין לסיום פעולה הא-סינכרונית, ואז ינסה שוב לעבד שוב מאפס. React יציג את ניסיון החוזר בעבודה, ומבלי לחסום את הדפדפן.
- אפקטי פריסה עם Suspense: כאשר עץ מושהה מחדש וחוזר ל-fallback, React ינקה כעת כאשר אפקטי פריסה, הוא ייצור אותם מחדש כאשר התוכן בתוך הגבול יוצג שוב. זה פותר בעיה שמנעה מספריות רכיבים למדוד נכון את הפריסה כאשר used עם Suspense.
- דרישות סביבת JS חדשות: React תלוי כעת בשימוש הדפדפנים מודרניות כולל
Promise,Symbolו-Object.assign. אם אתה תומך בדפדפנים ובמכשירים יש יותר כגון Internet Explorer צור אותם מספקים תכלית דפדפן מודרנית מקורי או שיש יישומים מזמינים תואמים, שכלול polyfill גלובלי ביישום המף שלך.
שינויים בולטים אחרים
React
- רכיבים יכולים לעבד את
undefined: React כבר לא מזהיר אם אתה מחזירundefinedצריך. זה יוצר את ערכי החזרת הרכיב המותר לעולים בקנה אחד עם הערכים המותרים באמצע רכיבי עץ. אנו מציעים use לנטר כדי למנוע טעויות כמו שכחתreturnstatement לפני JSX. - בבדיקות, אזהרות
actהן כרגע הסכמה: אם אתה מפעיל בדיקות מקצה לקצה, אזהרותactאינן נחוצות. הצגנו מנגנון הצטרפות כך אתם צריכים להפעיל אותם רק עבור בדיקות יחידה שבהן הם use מועילים. - אין אזהרה לגבי
setStateעל רכיבים לא מורכבים: בעבר, React הזהיר על דליפות memory כאשר אתה קורא ל-setStateעל רכיב לא מותקן. אזהרה זו נוספה עבור מנויים, אבל נתקלים בה בעיקר בתרחישים היא הגדרת הגדרהsetStateבסדר, ופתרונות עוקים מחמירים את הקוד. הסרנו אזהרה זו. - אין דיכוי של יומני מסוף: כאשר אתה use מצב קפדני, React מעבד כל רכיב פעמיים כדי לעזור לך למצוא לוואי בלתי צפויות. ב-React 17, דיחקנו את יומני המסוף עבור אחד משני העיבודים כדי להקל על הקריאה של היומנים. בתגובה ל-[משוב מהקהילה](
undefinedלגבי זה מבלבל, הסרנו את הדיכוי. במקום זאת, אם התקנתם את React DevTools, העיבודים של היומן השני יוצגו באפור, ותהיה אפשרות (כבוי כברירת מחדל) לדכא אותם לחלוטין. - שימוש משופר ב-memory: React מנקה עכשיו שדות פנימיות נוספות בעת ביטול הרכבה, מה שהופך את ההשפעה של דליפות memory לא מתוקנות שעשויות להתקיים בקוד האפליקציה שלך פחות חמורה.
React DOM שרת
renderToString: לא ישוגה עוד בזמן השעיה בשרת. במקום זאת, הוא יפלוט את ה-fallback HTML עבור גבול<Suspense>הקרוב ביותר כאשר ינסה שוב לעבד אותו תוכן בלקוח. עדיין מומלץ לעבור לסטרימינג API כמוrenderToPipeableStreamאוrenderToReadableStreamבמקום זאת.renderToStaticMarkup: לא ישוגה עוד בזמן השעיה בשרת. במקום זאת, הוא יפלוט את ה-fallback HTML עבור גבול<Suspense>הקרוב ביותר.
יומן שינויים
אתה יכול לראות את יומן השינויים המלא כאן.