Kodokon kodokon.com

การยก state ขึ้นและการแบ่งปันข้อมูล

วาง state แต่ละส่วนไว้ที่บรรพบุรุษร่วมที่ใกล้ที่สุดเพื่อแบ่งปันข้อมูลระหว่างหลายคอมโพเนนต์โดยไม่ต้องทำสำเนาซ้ำ

7 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

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

JSX
import { useState } from "react";

function ProductPage({ products }) {
  const [query, setQuery] = useState("");

  return (
    <>
      <SearchBar query={query} onChange={setQuery} />
      <ProductList products={products} query={query} />
    </>
  );
}
คอมโพเนนต์แม่เป็นเจ้าของ query และแบ่งปันให้ลูกทั้งสอง

ลูก ๆ จะกลายเป็นคอมโพเนนต์ แบบควบคุม (controlled): พวกมันรับค่าแบบอ่านอย่างเดียว และหากต้องการเปลี่ยนค่า ให้เรียกฟังก์ชัน callback ที่คอมโพเนนต์แม่จัดเตรียมไว้ ข้อมูลไหลลงผ่าน props ส่วนคำร้องขอเปลี่ยนแปลงไหลขึ้นผ่านฟังก์ชัน การไหลทางเดียวนี้ทำให้ติดตามพฤติกรรมของแอปพลิเคชันได้ง่าย

JSX
function SearchBar({ query, onChange }) {
  return (
    <input
      value={query}
      onChange={(e) => onChange(e.target.value)}
      placeholder="Search for a product"
    />
  );
}

function ProductList({ products, query }) {
  const visible = products.filter((p) =>
    p.name.toLowerCase().includes(query.toLowerCase())
  );
  return (
    <ul>
      {visible.map((p) => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}
SearchBar ร้องขอการเปลี่ยนแปลง ส่วน ProductList สะท้อนผลของมัน

ข้อมูลทุกชิ้นต้องมี แหล่งความจริงเพียงหนึ่งเดียว (single source of truth) หากคอมโพเนนต์สองตัวต่างเก็บสำเนาของ state เดียวกันไว้เอง สำเนาเหล่านั้นจะเบี่ยงเบนจากกันในที่สุด: ตัวหนึ่งถูกอัปเดต อีกตัวไม่ถูก และส่วนต่อประสานก็จะขัดแย้งกันเอง การยก state ขึ้นจะขจัดความเสี่ยงนั้น เมื่อข้อมูลต้องข้ามหลายระดับ การประกอบ (composition) (บทเรียนถัดไป) และต่อมา context จะช่วยลดภาระการส่ง props

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. คุณควรวาง state ที่คอมโพเนนต์พี่น้องสองตัวต้องใช้ไว้ที่ไหน?
    • ในคอมโพเนนต์พี่น้องตัวแรกจากสองตัว ซึ่งจะส่งต่อให้อีกตัว
    • ในบรรพบุรุษร่วมที่ใกล้ที่สุดของทั้งคู่
    • ในตัวแปรส่วนกลางที่ประกาศไว้นอก React
    • ในพี่น้องแต่ละตัวจากสองตัว โดยซิงค์กันด้วยมือ
  2. คอมโพเนนต์ลูกจะแก้ไข state ที่เป็นของคอมโพเนนต์แม่ได้อย่างไร?
    • โดยแก้ไข prop ที่ได้รับมาโดยตรง
    • โดยเรียกฟังก์ชัน callback ที่คอมโพเนนต์แม่ส่งมาเป็น prop
    • โดยใช้ useState ด้วยค่าเริ่มต้นเดียวกับคอมโพเนนต์แม่
  3. ทำไมจึงควรเลี่ยงการเก็บข้อมูลเดียวกันไว้ใน state สองส่วนที่ต่างกัน?
    • มันใช้หน่วยความจำมากเกินไป
    • React ห้ามเรียก useState สองครั้งด้วยค่าเริ่มต้นเดียวกัน
    • สำเนาทั้งสองจะหลุดจากการซิงค์กันในที่สุดและส่วนต่อประสานจะขัดแย้งกันเอง