สิ้นสุดการรอคอย!

React หนึ่งในไลบรารี JavaScript ที่ใช้กันอย่างแพร่หลายที่สุด ในที่สุดก็ได้เปิดตัวตัวเลือกการเปิดตัวของเวอร์ชัน 18 หรือ React 18 ที่รอคอยอย่างสูง ซึ่งหมายความว่าจะมีการเปลี่ยนแปลงเพียงเล็กน้อยเท่านั้นที่คาดว่าจะเกิดขึ้นในเวอร์ชันสุดท้าย/เสถียร

จำเป็นต้องมีความรู้เกี่ยวกับ React เพื่อทำความเข้าใจการอัปเดต React 18 หากคุณเป็นมือใหม่ เพียงทำตาม บทความ นี้เพื่อดูแผนงานใน React

มาดูกันว่าได้อะไรบ้าง!

API รูทใหม่

React 18 มีรูท API สองตัว ได้แก่ API รูทเก่าและรูทใหม่

Root API คืออะไร

ตามเอกสารอย่างเป็นทางการของ React “รูท” เป็นตัวชี้ไปยังโครงสร้างข้อมูลระดับบนสุดของ React เพื่อติดตามแผนผังที่จะเรนเดอร์

API รากดั้งเดิม

API รากที่มีอยู่เรียกว่า ReactDOM.render ปัจจุบัน รูทแนบอยู่กับองค์ประกอบ DOM และสามารถเข้าถึงได้ผ่านโหนด DOM

มันจะทำงานได้อย่างแม่นยำเหมือนกับใน React 17 อย่างไรก็ตาม คอนโซลจะส่งคำเตือนที่ระบุถึงการเลิกใช้งานและการย้ายไปยัง API ล่าสุด

import  React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import App from './App
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

API รูทใหม่

มันมาพร้อมกับ ReactDOM.createRoot เปิดใช้งานตัวเรนเดอร์พร้อมกันใหม่และเป็นประตูสู่การปรับปรุงทั้งหมดที่นำมาใช้กับ ปฏิกิริยา 18.

import * as ReactDOMClient from 'react-dom/client';
import App from 'App';

const container = document.getElementById('app');

// Create a root.
const root = ReactDOMClient.createRoot(container);

// Initial render: Render an element to the root.
root.render(<App tab="home" />);

// During an update, there's no need to pass the container again.
root.render(<App tab="profile" />);

ฟังก์ชัน createRoot จะสร้างรูทก่อน จากนั้นจึงใช้เมธอด render ที่จะเรียกใช้

จะจัดการความชุ่มชื้นด้วย Root API ใหม่ได้อย่างไร

ขณะนี้สามารถจัดการไฮเดรชั่นผ่าน ไฮเดรตรูท API

import * as ReactDOMClient from 'react-dom/client';
import App from 'App';

const container = document.getElementById('app');
//Before 
// Render with hydration.
ReactDOM.hydrate(<App tab="home" />, container);
//After
// Create *and* render a root with hydration.
const root = ReactDOMClient.hydrateRoot(container, <App button="add" />);

// You can later update it.
root.render(<App button="update" />);

Render Callback และ Root API ใหม่

การเรียกกลับการเรนเดอร์จะถูกลบออกเนื่องจากไม่สามารถรองรับการปรับปรุงที่ให้ไว้ผ่านการเพิ่มน้ำบางส่วนและการสตรีม SSR

import * as ReactDOMClient from 'react-dom/client';

const rootElement = document.getElementById("root");
// Don't do this
ReactDOMClient.render(<App />, rootElement, () => console.log("renderered"));
// Do this
const root = ReactDOMClient.createRoot(rootElement);
root.render(<App callback={() => console.log("renderered")} />);

React แนะนำให้ใช้ requestIdleCallback, setTimeout หรือการเรียกกลับอ้างอิงบนรูทแทน

สรุปความแตกต่างระหว่าง API ดั้งเดิมและ API รูทใหม่

  • ลบการเรียกกลับการเรนเดอร์ออกแล้ว และการทำงานของฟังก์ชันไฮเดรชั่นก็เปลี่ยนไป
  • รูทคือออบเจ็กต์ และฟังก์ชันใดๆ ที่จะอัปเดตรูทจะถูกนำไปใช้กับออบเจ็กต์นี้ แทนที่จะใช้กับ DOM

การผสมอัตโนมัติ

คุณเคยอัปเดตหลายสถานะในฟังก์ชันเดียวที่เรียกโดยตัวจัดการเหตุการณ์หรือไม่? คุณอาจสังเกตเห็นว่าสถานะทั้งหมดได้รับการอัปเดตในการเรนเดอร์ครั้งเดียว เรียกว่าการแบทช์อัตโนมัติ

การแบทช์คือการที่ React จัดกลุ่มการอัปเดตหลายสถานะเป็นการเรนเดอร์ซ้ำครั้งเดียวเพื่อประสิทธิภาพที่ดีขึ้น

ก่อน React 18 การแบทช์จะทำในตัวจัดการเหตุการณ์ React ตามค่าเริ่มต้นเท่านั้น

ก้าวไปข้างหน้าด้วย Root API ใหม่ การแบทช์สามารถทำได้โดยไม่คำนึงถึงต้นทาง เช่น คำสัญญา setTimeout ตัวจัดการเหตุการณ์ดั้งเดิม การอัปเดตจะปรับปรุงประสิทธิภาพโดยรวมและเวลาในการเรนเดอร์

ปิดการใช้งานแบทช์อัตโนมัติ

หากกรณีการใช้งานจำเป็นต้องอัปเดตสถานะและรอการตอบสนองก่อนที่จะดำเนินการอื่น ReactDOM flushSync()เข้ามาช่วยเหลือ

import { flushSync } from 'react-dom';

function handleClick() {
  flushSync(() => {
    // setState function
  });
  // React has updated the DOM by now
  flushSync(() => {
     // setState function
  });
  // React has updated the DOM by now
}

การเรนเดอร์ฝั่งเซิร์ฟเวอร์อย่างใจจดใจจ่อ / สตรีมมิ่ง (SSR) และไฮเดรชั่นแบบเลือก

ในภาษาของคนธรรมดา การเรนเดอร์ฝั่งเซิร์ฟเวอร์หมายถึงการสร้างเนื้อหา HTML บนเซิร์ฟเวอร์และให้บริการแก่ลูกค้าจนกว่า JavaScript จะโหลดและให้บริการทั้งหมด

ข้อบกพร่องในสถาปัตยกรรม SSR React ปัจจุบัน

  • จะต้องโหลด JS ทั้งหมดก่อนการให้น้ำ จากนั้นส่วนประกอบต่างๆ จะกลายเป็นแบบโต้ตอบ
  • ข้อมูล เช่น การเรียก API จะต้องพร้อมแล้วบนฝั่งเซิร์ฟเวอร์เนื่องจากไม่ต้องรอ
  • ส่วนประกอบทั้งหมดจะต้องได้รับความชุ่มชื้นก่อนทำปฏิกิริยากับส่วนประกอบเหล่านั้น

ตอบสนอง 18 สถาปัตยกรรม SSR

ไม่น่าเป็นไปได้ที่ SSR ในปัจจุบันซึ่งเป็นไปตามแนวทาง "ทั้งหมดหรือไม่มีเลย" React 18 นำการเปลี่ยนแปลงที่ปฏิวัติวงการในเรื่องนี้โดยเปิดใช้งานการสตรีม HTML การเลือกไฮเดรชั่น และส่วนประกอบการโหลดแบบ Lazy Loading ใน SSR

1. การสตรีม HTML

การล้อมส่วนประกอบใดๆ ด้วย ‹suspense›‹/suspense›จะเป็นการบอกให้ React ไม่ต้องรอส่วนประกอบนั้น แต่จะเริ่มสตรีม HTML แทน และเมื่อข้อมูลสำหรับโค้ดนั้นซึ่งรวมอยู่ใน Suspense พร้อมบนเซิร์ฟเวอร์ HTML เพิ่มเติมจะถูกส่งไปยังสตรีมเดียวกันโดยมี JS อินไลน์ขั้นต่ำเพื่อวางในตำแหน่งที่ถูกต้อง

สำหรับการสตรีม HTML บนเซิร์ฟเวอร์ ให้ใช้ renderToPipeableStream API แทน renderToString

จะช่วยเอาชนะปัญหาการมีข้อมูลครบถ้วนก่อนเรนเดอร์สิ่งใดๆ

2. เลือก Hydration และ Lazy Loading บน SSR

ฟีเจอร์ Lazy ของ React ช่วยให้สามารถโหลดแบบ Lazy Loading บนฝั่งไคลเอ็นต์ได้ กล่าวคือ เฉพาะ JS ของส่วนประกอบที่จำเป็นเท่านั้นที่จะถูกโหลดแทนที่จะโหลดทั้งแอป

ก่อนที่จะใช้ไฮเดรชั่นแบบเลือก คุณต้องเลือกใช้ createRoot API ใหม่

การห่อผลิตภัณฑ์จะบอก React ให้ปลดบล็อกส่วนประกอบที่เหลือจากการสตรีม และไม่ต้องรอโหลด JS ทั้งหมดก่อนที่จะเติมน้ำ

ในขณะที่ส่วนประกอบต่างๆ กำลังถูกทำให้ชุ่มชื้น React จะจัดลำดับความสำคัญของส่วนที่เร่งด่วนที่สุดของหน้าจอตามการโต้ตอบของผู้ใช้

import { lazy } from 'react';

const Products = lazy(() => import('./products.js'));

<Suspense fallback={<Spinner />}>
  <Products />
</Suspense>

API ใหม่

1. การเรนเดอร์พร้อมกัน

  • เริ่มต้นการเปลี่ยนผ่าน API

การทำงานกับข้อมูลจำนวนมหาศาลและการอัปเดตสถานะขนาดใหญ่มักจะทำให้ UI ช้าลงหรือค้าง

startTransition API เข้ามาช่วยเหลือเมื่อเปลี่ยนการอัปเดตสถานะเป็นการอัปเดตที่ไม่เร่งด่วน และดำเนินงานที่ซับซ้อนในเบื้องหลัง ประสบการณ์ผู้ใช้ยังคงราบรื่น

import { useTransition, startTransition } from 'react';
// Urgent: Show what was typed
setInputValue(input);

// Mark any state updates inside as transitions
startTransition(() => {
  // Transition: Show the results
  setSearchQuery(input);
});

นอกจากนี้ยังมี useTransitionhook เพื่อตรวจสอบสถานะของการเปลี่ยน

import { useTransition } from 'react';

const [isPending, startTransition] = useTransition();
{isPending && <Spinner />}
  • ใช้DeferredValue
import { useDeferredValue } from "react";
const deferredValue = useDeferredValue(text, { timeoutMs: 2000 });

hook ส่งกลับเวอร์ชันที่เลื่อนออกไปของค่าที่ส่งผ่าน โดยทั่วไปจะใช้เพื่อให้อินเทอร์เฟซตอบสนองเมื่อคุณมีบางสิ่งที่แสดงผลทันทีตามอินพุตของผู้ใช้และบางสิ่งที่ต้องรอการดึงข้อมูล

<แข็งแกร่ง>2. รหัสการใช้งาน

useId เป็น API สำหรับสร้าง ID เฉพาะบนไคลเอนต์และเซิร์ฟเวอร์ ในขณะเดียวกันก็หลีกเลี่ยงไม่ให้ข้อมูลไม่ตรงกัน

const id = useId();
<input type="checkbox" name="react" id={id} />

การปรับปรุงในเรื่อง Suspense ด้วย SuspenseList

SuspenseList เริ่มทำงานเมื่อองค์ประกอบหลายรายการต้องการการดึงข้อมูลและคำสั่งซื้อที่คาดเดาไม่ได้

SuspenseList ดำเนินการเฉพาะกับส่วนประกอบ Suspense และ SuspenseList ที่ใกล้เคียงที่สุดด้านล่างเท่านั้น มันไม่ได้ค้นหาขอบเขตที่ลึกกว่าหนึ่งระดับ อย่างไรก็ตาม คุณสามารถซ้อนส่วนประกอบ SuspenseList หลายรายการเข้าด้วยกันเพื่อสร้างกริดได้

<SuspenseList revealOrder="forwards">
  <Suspense fallback={'Loading...'}>
    <ProfilePicture id={1} />
  </Suspense>
  <Suspense fallback={'Loading...'}>
    <ProfilePicture id={2} />
  </Suspense>
  <Suspense fallback={'Loading...'}>
    <ProfilePicture id={3} />
  </Suspense>
  ...
</SuspenseList>

ด้วย SuspenseList ส่วนประกอบจะไม่แสดงจนกว่าส่วนประกอบก่อนหน้าจะดึงข้อมูลและพร้อมแล้ว

ต้องใช้อุปกรณ์ประกอบฉากสองรายการ: revealOrder (ไปข้างหน้า ถอยหลัง รวมกัน)กำหนดลำดับที่ส่วนประกอบในรายการจะแสดงและ ส่วนท้าย (ยุบ ซ่อน) กำหนดวิธีการยกเลิกการโหลดรายการใน SuspenseList จะปรากฏขึ้น

สรุป

ด้วยการเปลี่ยนแปลงทางสถาปัตยกรรม React 18 กำลังนำเสนอ ชุมชน React รู้สึกตื่นเต้น มันจะมอบ UI, UX, CX ที่ดีขึ้น และเว็บแอปที่เชื่อถือได้และมีประสิทธิภาพมากขึ้นอยู่ใกล้แค่เอื้อม

คอยติดตาม!

มาเชื่อมต่อกับ LinkedIn กันเถอะ