คุณสมบัติใหม่ใน React เวอร์ชันหลักใหม่

คุณสมบัติใหม่ใน React 18 คืออะไร

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

ปฏิกิริยาพร้อมกัน

ฟังดูแปลก ๆ แต่ก็ง่ายกว่าที่บุคคลจะคิดและปรับปรุงได้ ไม่ใช่แค่งานของการพัฒนาเท่านั้น แต่ยังรวมถึงความเร็วและประสบการณ์ผู้ใช้ด้วย มันเป็นเบรกพอยต์ใน React เพราะมันเปลี่ยนวิธีที่ React เรนเดอร์ UI เมื่อเปรียบเทียบกับเวอร์ชันก่อนหน้า เป็นผลให้ผู้ใช้สามารถโต้ตอบกับเพจได้เร็วขึ้น มอบประสบการณ์ที่ราบรื่นยิ่งขึ้นแม้บนเพจที่เน้นข้อมูลเป็นศูนย์กลางก็ตาม และแน่นอนว่ามันเป็นพื้นฐานของคุณสมบัติใหม่และ hooks ที่เปิดตัวพร้อมกับเวอร์ชันหลัก 18

แต่เดี๋ยวก่อน. ภาวะพร้อมกันคืออะไร? จากเอกสาร React:

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

มันหมายความว่าอะไร? การเรนเดอร์ใน React เวอร์ชันก่อนหน้าไม่สามารถถูกขัดจังหวะได้ เมื่อคุณร้องขอ React จะเรนเดอร์มุมมอง และหากมีการเปลี่ยนแปลงใดๆ คุณจะต้องเรนเดอร์อีกครั้ง ขณะนี้ เมื่อมีการทำงานพร้อมกัน คุณสามารถมีงานหลายอย่างอยู่เบื้องหลัง และตัดสินใจว่างานใดที่เร่งด่วนที่สุดในการจัดลำดับความสำคัญ ไม่ได้หมายความว่า React จะทำงานหลายอย่างในเวลาเดียวกัน แต่ตอนนี้สามารถเลือกระหว่างงานเหล่านั้นได้ ด้วยการใช้งานใหม่นี้ React สามารถเริ่มการเรนเดอร์แผนผังส่วนประกอบต่างๆ หยุดชั่วคราวระหว่างการดำเนินการเพื่อทำงานอื่นให้สำเร็จ (เพื่อเรนเดอร์แผนผังย่อยของส่วนประกอบอื่น) จากนั้นจึงเสร็จสิ้นการดำเนินการครั้งแรก

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

ตัวอย่างที่ชัดเจนคือการใช้ useStatehook ก่อนที่จะออกเวอร์ชันหลักใหม่ React สามารถอัปเดตได้เพียงสถานะเดียวต่อการดำเนินการ ซึ่งทั้งหมดนี้ถือเป็นเรื่องเร่งด่วน แต่ตอนนี้ ด้วยกระบวนการทำงานพร้อมกันใหม่และ API เช่น startTransition คุณสามารถทำเครื่องหมายสถานะการอัปเดตว่า "ไม่เร่งด่วน" ได้ ทำให้การดำเนินการที่สำคัญอื่นๆ มาเป็นอันดับแรกในสแต็ก

โต้ตอบใจจดใจจ่อ ‹ส่วนประกอบ› ในฝั่งไคลเอ็นต์

องค์ประกอบใจจดใจจ่อไม่ใช่แนวคิดใหม่ เปิดตัวใน React 16.6 แต่มีข้อจำกัดหลายประการ และไม่สามารถใช้สำหรับการดึงข้อมูลได้ สิ่งนี้มีการเปลี่ยนแปลงในรีลีสหลักล่าสุด และตอนนี้เราสามารถใช้คอมโพเนนต์ ‹Suspense› สำหรับการดึงข้อมูลได้

ส่วนประกอบ ‹Suspense› ทำหน้าที่อะไร? ช่วยลดความยุ่งยากในการดึงข้อมูลแบบอะซิงโครนัสและการแสดงการโหลด ตอนนี้สามารถพันรอบส่วนประกอบที่จัดการการดึงข้อมูลได้ ทำให้นักพัฒนาสามารถแสดงส่วนประกอบของตัวโหลดที่เขียนโค้ดในลักษณะที่ประกาศในเลย์เอาต์ของพวกเขาได้

นี่คือตัวอย่างวิธีการจัดการก่อนหน้านี้:

import React, { useState, useEffect } from "react";
import axios from "axios";
import ListUsers from "./ListUsers";


const AsyncComponent = () => {


 const [loading, setLoading] = useState(true);
 const [data, setData] = useState(null);


 useEffect(() => {
   const fetchData = async () => {
     try {
       const response = await axios.get(
         "https://642d55ab66a20ec9ce9a9e41.mockapi.io/users"
       );
       setData(response.data);
       setLoading(false);
     } catch (e) {
       setLoading(false);
       setData([]);
     }
   };
   fetchData();
 });
 return (
   <>
     {loading ? (
       <p>Loading ...</p>
     ) : (
       <ListUsers list={data} />
     )}
   </>
 );
};
export default AsyncComponent;

จากนั้นแอปของเราจะเป็นดังนี้:

import React from "react";
import "./App.css";
import AsyncComponent from "./components/AsyncComponent";


function App() {
 return (
   <div className="App">
     <h1>List of Users</h1>
     <AsyncComponent />
   </div>
 );
}
export default App;

Thas มีการเปลี่ยนแปลงด้วย React เวอร์ชันใหม่ ขั้นแรก เราจะตรวจสอบว่าแอป React ของเรามีลักษณะอย่างไรด้วยส่วนประกอบ ‹Suspense›:

mport React, { Suspense } from "react";
import "./App.css";
import AsyncSuspendableComponent from "./components/AsyncSuspendableComponent";


function App() {
 return (
   <div className="App">
     <h1>Suspense Example: Full List of Users</h1>
     <Suspense fallback={<p>Loading, please wait...</p>}>
       <AsyncSuspendableComponent />
     </Suspense>
   </div>
 );
}
export default App;

ตรรกะในการโหลดได้รับการสรุปจากภายในองค์ประกอบ Async เราทำให้ตรรกะในการโหลดเป็นอิสระจากองค์ประกอบการดึงข้อมูล ซึ่งหมายความว่าเราสามารถเปลี่ยนวิธีจัดการลำดับการโหลดของเราได้โดยไม่ต้องแก้ไขแต่ละองค์ประกอบที่ทำงานขึ้นอยู่กับการดึงข้อมูล นอกจากนั้น เรายังสามารถซ้อนส่วนประกอบ ‹Suspense› ไว้ด้วยกันได้ ทำให้เราสามารถแสดงตัวโหลดสำหรับทั้งส่วนหรือส่วนประกอบย่อยของส่วนนั้นได้ แน่นอนว่าเรามีส่วนประกอบที่ตอนนี้สะอาดกว่ามากและบำรุงรักษาง่ายกว่ามาก

import React from "react";
import ListUsers from "./ListUsers";
import { fetchData } from "../lib/suspense-demo-api";
const resource = fetchData();


const AsyncSuspendableComponent = () => {
 const data = resource.data.read();
 return <ListUsers list={data} />;
};
export default AsyncSuspendableComponent;

โปรดทราบว่าทีม React ไม่แนะนำให้ใช้ส่วนประกอบ ‹Suspense› ด้วยตัวคุณเอง เนื่องจากการใช้งานแบบ “เฉพาะกิจ” นี้ ในทางตรงกันข้าม แนะนำให้ใช้เฟรมเวิร์กที่รวมตรรกะสำหรับการดึงข้อมูลด้วย Suspense แล้ว เช่น Next.js, Gatbsy, Relay และ Apollo

ใจจดใจจ่อบนเซิร์ฟเวอร์

ไม่เพียงแต่ในฝั่งไคลเอ็นต์เท่านั้น แต่ยังพูดถึงเซิร์ฟเวอร์ด้วย ฟีเจอร์ที่น่าสงสัยใน React 18 ขอแนะนำ:

  1. การแยกรหัสบนเซิร์ฟเวอร์
  2. การเรนเดอร์สตรีมมิ่งบนเซิร์ฟเวอร์

การเรนเดอร์ไคลเอนต์เทียบกับการเรนเดอร์เซิร์ฟเวอร์

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

เพื่อเพิ่มประสิทธิภาพนี้ เราสามารถใช้การเรนเดอร์เซิร์ฟเวอร์: เราโหลดแนวทางแรกของ HTML ในเซิร์ฟเวอร์และส่งไปยังไคลเอนต์ ในระหว่างนี้ เซิร์ฟเวอร์กำลังรอการดึงข้อมูลหรือเตรียมทรัพยากรที่จำเป็น JavaScript แต่จนกว่าจะเกิดเหตุการณ์เช่นนี้ คุณให้ข้อมูลบางอย่างแก่ผู้ใช้และเตรียมมุมมองสำหรับ "ไฮเดรต" ด้วยข้อมูลที่เซิร์ฟเวอร์กำลังรอ

ปัญหานี้คืออะไร? ดูเหมือนจะเป็นเทคนิคที่มีประโยชน์มาก แต่ข้อจำกัดของการเรนเดอร์เซิร์ฟเวอร์เหมือนเช่นใน React 17 หรือก่อนหน้าก็คือคุณเรนเดอร์ทั้งหมดหรือไม่แสดงเลย และอาจมีบางส่วนของแอปพลิเคชันของคุณที่ใช้เวลานานมากในการดึงข้อมูล ดังนั้นคุณจะไม่สามารถเติมน้ำให้กับเว็บทั้งหมดของคุณได้ นั่นคือตอนที่ Suspense‹component› เข้ามาในฉากในเซิร์ฟเวอร์

ด้วยความช่วยเหลือของใจจดใจจ่อ คุณสามารถรวมส่วนที่ช้าของแอปของคุณไว้ภายในส่วนประกอบ Suspense และทำให้การโหลดส่วนประกอบนี้ล่าช้า แต่ไม่ใช่ทั้งแอป นั่นหมายความว่าใน React 18 ส่วนประกอบที่ช้าสามารถไปกับตัวยึดตำแหน่ง HTML ทั้งหมดที่ส่งจากเซิร์ฟเวอร์และรอให้ไฮเดรตเป็นอิสระจากส่วนประกอบอื่น ๆ

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

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

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

ก่อนการเปลี่ยนแปลงนี้ การอัปเดตสถานะนี้ไม่ได้ดำเนินการเป็นกลุ่ม ยกเว้นว่าตัวจัดการเหตุการณ์บางตัว เช่น สัญญาหรือเหตุการณ์ onClick ซึ่งการเรียกกลับจะเปลี่ยนหลายสถานะเมื่อมีการเรียก ดังนี้:

const handleOnClick=>{
  setSomeState();
  setAnotherState();
  setThirdState(); 
}

/* Before react 18, when setting states in events handlers, we can "batch"
events and allow just one render. */

การเปลี่ยนแปลงของรัฐ

นี่เป็นแนวคิดใหม่ใน React โดยให้จัดลำดับความสำคัญระหว่างการอัปเดตสถานะในสองสถานการณ์: เร่งด่วนและไม่เร่งด่วน มันหมายความว่าอะไร?

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

การอัปเดตที่ไม่เร่งด่วนเหล่านี้เรียกว่าการเปลี่ยนภาพ ด้วยการทำเครื่องหมายการอัปเดต UI ที่ไม่เร่งด่วนว่าเป็น “การเปลี่ยนแปลง” React จะรู้ว่าการอัปเดตใดที่ต้องจัดลำดับความสำคัญ ทำให้ง่ายต่อการเพิ่มประสิทธิภาพการเรนเดอร์และกำจัดการเรนเดอร์เก่า ๆ

ก่อนฟีเจอร์นี้ เพื่อให้เกิดเอฟเฟกต์นี้ นักพัฒนาจึงใช้เทคนิคเช่นการดีเด้ง ขณะนี้ ด้วย API ใหม่นี้ ทำให้พฤติกรรมนำไปใช้ได้ง่ายขึ้น

import { startTransition } from 'react';

// Urgent: Show what was typed
setInputValue(input);

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

แต่การเปลี่ยนภาพแตกต่างจาก debouncing หรือ setTimeOut คืออะไร?

  1. startTransition ดำเนินการทันที ไม่เหมือน setTimeout
  2. setTimeout มีการรับประกันความล่าช้า ในขณะที่ความล่าช้าของ startTransition ขึ้นอยู่กับความเร็วของอุปกรณ์ และการแสดงผลเร่งด่วนอื่นๆ
  3. การอัปเดต startTransition สามารถถูกขัดจังหวะได้ ซึ่งต่างจาก setTimeout และจะไม่ทำให้เพจค้าง
  4. React สามารถติดตามสถานะรอดำเนินการให้คุณได้เมื่อทำเครื่องหมายด้วย startTransition

โหมดเข้มงวด

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

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

สรุป

ดังนั้นเราจึงได้ให้รายละเอียดเกี่ยวกับฟีเจอร์ใหม่ต่อไปนี้ที่มีใน React 18:

  1. เห็นพ้องต้องกัน
  2. ใจจดใจจ่อ
  3. การผสมอัตโนมัติ
  4. การเปลี่ยนผ่าน
  5. โหมดเข้มงวด

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