วิธีการทำงานผ่านสเตตของคอมโพเนนต์ลูกใน React

ให้อาร์เรย์ผลิตภัณฑ์ของเราตอนนี้มีลักษณะ ดังต่อไปนี้:

jsxconst initProds = [
  {id: id(), name: 'prod1', cost: 'cost1', catg: 'catg1'},
  {id: id(), name: 'prod2', cost: 'cost2', catg: 'catg2'},
  {id: id(), name: 'prod3', cost: 'cost3', catg: 'catg3'},
];

มาแสดงผลิตภัณฑ์เหล่านี้ในรูปแบบ HTML ตารางกัน และทำให้เมื่อคลิกที่ เซลล์ใดๆ ของตาราง ในเซลล์นั้นจะปรากฏ input สำหรับแก้ไข เพื่อแก้ปัญหา เราจะสร้าง 3 คอมโพเนนต์

คอมโพเนนต์ Products จะเก็บสเตต ที่มีผลิตภัณฑ์และใช้คอมโพเนนต์ Product เพื่อแสดงผลผลิตภัณฑ์ คอมโพเนนต์ Product จะใช้คอมโพเนนต์ ProductField ในการแสดงผลฟิลด์ ของผลิตภัณฑ์ (ชื่อ ราคา หมวดหมู่)

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

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

jsxconst initProds = [
  [
    {field: 'name', value: 'prod1', isEdit: false},
    {field: 'cost', value: 'cost1', isEdit: false},
    {field: 'catg', value: 'catg1', isEdit: false},
  ],
  [
    {field: 'name', value: 'prod2', isEdit: false},
    {field: 'cost', value: 'cost2', isEdit: false},
    {field: 'catg', value: 'catg2', isEdit: false},
  ],
  [
    {field: 'name', value: 'prod3', isEdit: false},
    {field: 'cost', value: 'cost3', isEdit: false},
    {field: 'catg', value: 'catg3', isEdit: false},
  ],
]

อย่างไรก็ตาม เราจะไม่ทำสเตตแบบนั้น แต่จะใช้แบบเดิม เพียงแค่แต่ละ อินสแตนซ์ของคอมโพเนนต์ ProductField ด้วยสเตตของตัวเองจะควบคุม โหมด: แก้ไข หรือแสดง

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

มาเริ่มทำตามที่อธิบายกัน

คอมโพเนนต์ Products

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  function changeField(id, field, event) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod[field] = event.target.value;
      }
      
      return prod;
    }));
  }
  
  const rows = prods.map(prod => {
    return <Product
      key ={prod.id}
      id  ={prod.id}
      name={prod.name}
      cost={prod.cost}
      catg={prod.catg}
      changeField={changeField}
    />;
  });
  
  return <div>
    <table>
      <tbody>
        {rows}
      </tbody>
    </table>
  </div>;
}

คอมโพเนนต์ Product

jsxfunction Product({ id, name, cost, catg, changeField }) {
  return <tr>
    <ProductField id={id} text={name} type="name" changeField={changeField} />
    <ProductField id={id} text={cost} type="cost" changeField={changeField} />
    <ProductField id={id} text={catg} type="catg" changeField={changeField} />
  </tr>;
}

คอมโพเนนต์ ProductField

jsxfunction ProductField({ id, text, type, changeField }) {
  const [isEdit, setIsEdit] = useState(false);
  
  return <td>
    {
      isEdit
      ? <input
        value={text}
        onChange={event => changeField(id, type, event)}
        onBlur={() => setIsEdit(false)}
      />
      : <span onClick={() => setIsEdit(true)}>{text}</span>
    }
  </td>;
}

งานปฏิบัติ

Задание 1

ดำเนินการที่คล้ายกันกับคอมโพเนนต์ Users และ User ที่คุณสร้าง ในบทเรียนก่อนหน้านี้