ทำความเข้าใจกับคีย์ที่ไม่ซ้ำกันสำหรับอาร์เรย์ลูกใน React.js


655

ฉันกำลังสร้างส่วนประกอบ React ที่ยอมรับแหล่งข้อมูล JSON และสร้างตารางที่สามารถเรียงลำดับได้
แถวข้อมูลแบบไดนามิกแต่ละแถวมีคีย์เฉพาะที่กำหนดให้ แต่ฉันยังคงได้รับข้อผิดพลาด:

เด็กแต่ละคนในอาร์เรย์ควรมีเสา "คีย์" ที่ไม่ซ้ำกัน
ตรวจสอบวิธีการเรนเดอร์ของ TableComponent

TableComponentวิธีการแสดงผลของฉันกลับมา:

<table>
  <thead key="thead">
    <TableHeader columns={columnNames}/>
  </thead>
  <tbody key="tbody">
    { rows }
  </tbody>
</table>

TableHeaderองค์ประกอบเป็นแถวเดียวและยังมีความสำคัญที่ไม่ซ้ำกันที่ได้รับมอบหมาย

แต่ละrowin rowsสร้างจากส่วนประกอบที่มีคีย์เฉพาะ:

<TableRowItem key={item.id} data={item} columns={columnNames}/>

และTableRowItemดูเหมือนว่านี้:

var TableRowItem = React.createClass({
  render: function() {

    var td = function() {
        return this.props.columns.map(function(c) {
          return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
        }, this);
      }.bind(this);

    return (
      <tr>{ td(this.props.item) }</tr>
    )
  }
});

อะไรเป็นสาเหตุของข้อผิดพลาดที่ไม่เหมือนใครของ prop key?


7
แถวของคุณในอาร์เรย์ JS ควรมีkeyคุณสมบัติที่ไม่ซ้ำกัน มันจะช่วย ReactJS ในการค้นหาการอ้างอิงไปยังโหนด DOM ที่เหมาะสมและอัปเดตเฉพาะเนื้อหาภายในการมาร์กอัป แต่ไม่แสดงทั้งตาราง / แถวอีกครั้ง
Kiril

คุณสามารถแชร์rowsอาร์เรย์หรือมากกว่า jsfiddle ได้ดีกว่าหรือไม่ คุณไม่จำเป็นต้องให้keyทรัพย์สินในtheadและtbodyโดยวิธี
nilgun

ฉันเพิ่มองค์ประกอบแถวไปยังคำถามเดิม @nilgun
Brett DeWoody

3
เป็นไปได้หรือไม่ว่าบางรายการไม่มีรหัสหรือมี ID เดียวกัน
nilgun

คำตอบ:


621

คุณควรเพิ่มที่สำคัญให้เด็กแต่ละคนเช่นเดียวกับองค์ประกอบภายในของเด็กแต่ละคน

วิธีนี้ทำปฏิกิริยาสามารถจัดการการเปลี่ยนแปลง DOM ที่น้อยที่สุด

ในรหัสของคุณแต่ละคน<TableRowItem key={item.id} data={item} columns={columnNames}/>พยายามทำให้เด็กบางคนอยู่ข้างในโดยไม่มีรหัส

ตรวจสอบตัวอย่างนี้

ลองลบองค์ประกอบออกkey={i}จาก<b></b>div ภายใน (และตรวจสอบคอนโซล)

ในตัวอย่างถ้าเราไม่ให้กุญแจสำคัญในการที่<b>องค์ประกอบและเราต้องการที่จะปรับปรุงเท่านั้นobject.cityตอบสนองความต้องการที่จะกลับมาทำให้ทั้งแถว VS เพียงองค์ประกอบ

นี่คือรหัส:

var data = [{name:'Jhon', age:28, city:'HO'},
            {name:'Onhj', age:82, city:'HN'},
            {name:'Nohj', age:41, city:'IT'}
           ];

var Hello = React.createClass({

    render: function() {

      var _data = this.props.info;
      console.log(_data);
      return(
        <div>
            {_data.map(function(object, i){
               return <div className={"row"} key={i}> 
                          {[ object.name ,
                             // remove the key
                             <b className="fosfo" key={i}> {object.city} </b> , 
                             object.age
                          ]}
                      </div>; 
             })}
        </div>
       );
    }
});

React.render(<Hello info={data} />, document.body);

คำตอบที่โพสต์โดย@Chrisที่ด้านล่างจะมีรายละเอียดมากกว่าคำตอบนี้ โปรดดูที่https://stackoverflow.com/a/43892905/2325522

ตอบโต้เอกสารเกี่ยวกับความสำคัญของคีย์ในการกระทบยอด: Keys


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

1
คำตอบใช้ได้ผล Deke เพียงตรวจสอบให้แน่ใจว่าkeyค่าของเสานั้นไม่ซ้ำกันสำหรับแต่ละรายการและคุณวางkeyเสาไปยังส่วนประกอบที่ใกล้เคียงกับขอบเขตอาร์เรย์ ตัวอย่างเช่นใน React Native ก่อนอื่นฉันพยายามใส่keyprop ให้กับ<Text>องค์ประกอบ แต่ฉันมีที่จะนำไปส่วนประกอบซึ่งเป็นแม่ของ<View> <Text>ถ้า Array == [(ดู> ข้อความ), (ดู> ข้อความ)] คุณจะต้องใส่ลงใน View ไม่ใช่ข้อความ
scaryguy

239
เหตุใดจึงยากสำหรับ React ในการสร้างคีย์เฉพาะเอง
Davor Lucic

13
@DavorLucic นี่คือการสนทนา: github.com/facebook/react/issues/1342#issuecomment-39230939
koddo

5
นี่เป็นคำที่เป็นทางการในบันทึกการสนทนาที่เชื่อมโยงกับด้านบน: คีย์เกี่ยวกับตัวตนของสมาชิกของชุดและการสร้างกุญแจอัตโนมัติสำหรับรายการที่โผล่ออกมาจากตัวทำซ้ำโดยพลการอาจมีความเกี่ยวข้องกับประสิทธิภาพภายในปฏิกิริยา ห้องสมุด.
Sameers

523

ระวังเมื่อวนซ้ำอาร์เรย์!

เป็นความเข้าใจผิดที่พบบ่อยว่าการใช้ดัชนีขององค์ประกอบในอาร์เรย์เป็นวิธีที่ยอมรับได้ในการระงับข้อผิดพลาดที่คุณอาจคุ้นเคยกับ:

Each child in an array should have a unique "key" prop.

อย่างไรก็ตามในหลายกรณีมันไม่ได้เป็น! นี่คือการต่อต้านรูปแบบที่สามารถในบางสถานการณ์ที่นำไปสู่พฤติกรรมที่ไม่พึงประสงค์


ทำความเข้าใจกับkeyเสา

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

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

ผู้พัฒนา React กล่าวในปัญหา GitHub นี้ :

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

ในระยะสั้นkeyควรเป็น:

  • ที่ไม่ซ้ำกัน - ที่สำคัญไม่สามารถจะเหมือนกันกับที่ขององค์ประกอบพี่น้อง
  • คงที่ - กุญแจไม่ควรเปลี่ยนระหว่างเรนเดอร์


การใช้keyอุปกรณ์ประกอบฉาก

ตามคำอธิบายข้างต้นศึกษาตัวอย่างต่อไปนี้อย่างละเอียดและพยายามนำไปใช้เมื่อเป็นไปได้แนวทางที่แนะนำ


ไม่ดี (อาจเกิดขึ้น)

<tbody>
    {rows.map((row, i) => {
        return <ObjectRow key={i} />;
    })}
</tbody>

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

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

ในคำอื่น ๆ ในตอนแรกมีItem 1 key={0}เมื่อเราเพิ่มรายการที่สองรายการด้านบนจะกลายเป็นItem 2ตามด้วยItem 1เป็นรายการที่สอง อย่างไรก็ตามตอนนี้Item 1มีkey={1}และไม่ได้key={0}อีกต่อไป แต่Item 2ตอนนี้มีkey={0}!!

ดังนั้น React จึงคิดว่า<input>องค์ประกอบต่าง ๆ ไม่ได้เปลี่ยนไปเพราะItemปุ่ม with 0อยู่ด้านบนเสมอ!

เหตุใดบางครั้งวิธีนี้จึงไม่ดีเท่านั้น

วิธีการนี้มีความเสี่ยงเฉพาะเมื่ออาร์เรย์ถูกกรองจัดเรียงใหม่หรือรายการจะถูกเพิ่ม / ลบ หากเป็นแบบคงที่ตลอดเวลาแสดงว่าปลอดภัยอย่างสมบูรณ์ที่จะใช้ ตัวอย่างเช่นเมนูการนำทางเช่น["Home", "Products", "Contact us"]สามารถทำซ้ำได้อย่างปลอดภัยด้วยวิธีนี้เพราะคุณอาจไม่เคยเพิ่มลิงก์ใหม่หรือจัดเรียงใหม่

ในระยะสั้นนี่คือเมื่อคุณสามารถใช้ดัชนีอย่างปลอดภัยเป็นkey:

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

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


ที่เลวร้ายมาก

<tbody>
    {rows.map((row) => {
        return <ObjectRow key={Math.random()} />;
    })}
</tbody>

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

คีย์ที่ไม่เสถียร (เช่นที่สร้างโดยMath.random()) จะทำให้อินสแตนซ์ของคอมโพเนนต์จำนวนมากและโหนด DOM ถูกสร้างขึ้นใหม่โดยไม่จำเป็นซึ่งอาจทำให้ประสิทธิภาพการทำงานลดลงและสถานะที่หายไปในคอมโพเนนต์ย่อย


ดีมาก

<tbody>
    {rows.map((row) => {
        return <ObjectRow key={row.uniqueId} />;
    })}
</tbody>

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

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


ดี

componentWillMount() {
  let rows = this.props.rows.map(item => { 
    return {uid: SomeLibrary.generateUniqueID(), value: item};
  });
}

...

<tbody>
    {rows.map((row) => {
        return <ObjectRow key={row.uid} />;
    })}
</tbody>

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


1
ในเอกสารอย่างเป็นทางการพวกเขาใช้toString()ในการแปลงเป็นสตริงแทนที่จะปล่อยให้เป็นตัวเลข นี่เป็นสิ่งสำคัญที่ต้องจำไว้?
กิน

1
@skube ไม่คุณสามารถใช้จำนวนเต็มkeyเช่นกัน ไม่แน่ใจว่าทำไมพวกเขาถึงแปลงมัน
คริส

1
ฉันเดาว่าคุณสามารถใช้จำนวนเต็ม แต่ควรหรือไม่ ตามเอกสารของพวกเขาพวกเขาระบุว่า "... วิธีที่ดีที่สุดในการเลือกกุญแจคือการใช้สตริงที่ระบุตัวตนที่ไม่ซ้ำกัน ... " (เหมืองของเราที่เน้น)
skube

2
@ สกูบใช่ว่าเป็นที่ยอมรับอย่างสมบูรณ์ ตามที่ระบุไว้ในตัวอย่างข้างต้นคุณสามารถใช้ดัชนีของรายการของอาร์เรย์ที่วนซ้ำ (และนั่นคือจำนวนเต็ม) แม้รัฐเอกสาร: "เป็นรีสอร์ทสุดท้ายคุณสามารถส่งผ่านดัชนีของรายการในอาร์เรย์เป็นสำคัญ" สิ่งที่เกิดขึ้นก็คือแม้ว่าจะkeyเป็นสตริงเสมอ
คริส

3
@ farmcommand2 กุญแจถูกนำมาใช้เพื่อตอบสนองส่วนประกอบและความจำเป็นที่จะต้องไม่ซ้ำกันในหมู่พี่น้อง นี่คือที่ระบุไว้ข้างต้น ในคำอื่น ๆ ที่ไม่ซ้ำกันในอาร์เรย์
Chris

8

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

ฉันมีสถานที่ตั้งจำนวนมากที่สร้างรายการโดยใช้โครงสร้างด้านล่าง:

return (
    {myList.map(item => (
       <>
          <div class="some class"> 
             {item.someProperty} 
              ....
          </div>
       </>
     )}
 )

หลังจากการทดลองใช้และข้อผิดพลาดเล็กน้อย (และผิดหวังบางอย่าง) การเพิ่มคุณสมบัติหลักให้บล็อกด้านนอกสุดจะแก้ไขได้ โปรดทราบว่าขณะนี้แท็ก <> จะถูกแทนที่ด้วยแท็กทันที

return (

    {myList.map((item, index) => (
       <div key={index}>
          <div class="some class"> 
             {item.someProperty} 
              ....
          </div>
       </div>
     )}
 )

แน่นอนฉันใช้ดัชนีซ้ำ (ดัชนี) ซ้ำ ๆ เพื่อเติมค่าคีย์ในตัวอย่างด้านบน เป็นการดีที่คุณจะใช้สิ่งที่ไม่ซ้ำกับรายการ


นี่เป็นประโยชน์อย่างมากขอบคุณ! ฉันไม่ทราบด้วยซ้ำว่าฉันต้องวางไว้ในชั้นนอกสุด
Charles Smith

6

คำเตือน: เด็กแต่ละคนในอาร์เรย์หรือตัววนซ้ำควรมีเสา "คีย์" ที่ไม่ซ้ำกัน

นี่เป็นคำเตือนสำหรับไอเท็มอาเรย์ที่เราจะทำซ้ำมากกว่านั้นจะต้องมีความคล้ายคลึงกัน

React จัดการวนซ้ำการเรนเดอร์องค์ประกอบเป็นอาร์เรย์

วิธีที่ดีกว่าในการแก้ไขปัญหานี้คือให้ดัชนีในรายการอาร์เรย์ที่คุณจะทำซ้ำมากกว่าตัวอย่างเช่น:

class UsersState extends Component
    {
        state = {
            users: [
                {name:"shashank", age:20},
                {name:"vardan", age:30},
                {name:"somya", age:40}
            ]
        }
    render()
        {
            return(
                    <div>
                        {
                            this.state.users.map((user, index)=>{
                                return <UserState key={index} age={user.age}>{user.name}</UserState>
                            })
                        }
                    </div>
                )
        }

ดัชนีเป็นอุปกรณ์ตอบโต้ในตัว


2
วิธีการนี้อาจเป็นอันตรายหากจัดเรียงรายการใหม่ แต่ถ้าพวกเขายังคงนิ่งเงียบนี่ก็ใช้ได้
Chris

@chris ฉันเห็นด้วยอย่างสมบูรณ์กับคุณเพราะในกรณีนี้ดัชนีอาจมีการทำซ้ำ ดีกว่าที่จะใช้ค่าแบบไดนามิกสำหรับคีย์
Shashank Malviya

@chris ฉันเห็นด้วยกับความคิดเห็นของคุณ เราควรใช้ค่าแบบไดนามิกมากกว่าดัชนีเพราะอาจมีการทำซ้ำ เพื่อให้ง่ายฉันทำสิ่งนี้ Btw ขอบคุณสำหรับการสนับสนุนของคุณ (อัปโหลดแล้ว)
Shashank Malviya

6

เพียงเพิ่มคีย์เฉพาะลงในคอมโพเนนต์ของคุณ

data.map((marker)=>{
    return(
        <YourComponents 
            key={data.id}     // <----- unique key
        />
    );
})

6

ตรวจสอบ: key = undef !!!

คุณได้รับข้อความเตือนด้วย:

Each child in a list should have a unique "key" prop.

ถ้ารหัสของคุณถูกต้อง แต่ถ้าเปิด

<ObjectRow key={someValue} />

someValue ไม่ได้ถูกกำหนด !!! โปรดตรวจสอบเรื่องนี้ก่อน คุณสามารถประหยัดชั่วโมง


1

ทางออกที่ดีที่สุดของการกำหนดคีย์ที่ไม่ซ้ำกันในการตอบสนอง: ภายในแผนที่คุณเริ่มต้นโพสต์ชื่อแล้วคีย์กำหนดโดย key = {post.id} หรือในรหัสของฉันคุณเห็นฉันกำหนดไอเท็มชื่อจากนั้นฉันกำหนด key by key = {item.id }:

<div className="container">
                {posts.map(item =>(

                    <div className="card border-primary mb-3" key={item.id}>
                        <div className="card-header">{item.name}</div>
                    <div className="card-body" >
                <h4 className="card-title">{item.username}</h4>
                <p className="card-text">{item.email}</p>
                    </div>
                  </div>
                ))}
            </div>


0

นี่คือคำเตือน แต่อยู่นี้จะทำให้ปฏิกิริยาการแสดงผลได้เร็วขึ้นมาก ,

เนื่องจากReactต้องระบุแต่ละรายการในรายการโดยไม่ซ้ำกัน ให้บอกว่าสถานะขององค์ประกอบของรายการนั้นเปลี่ยนแปลงใน Reacts หรือไม่Virtual DOMReact จำเป็นต้องทราบว่าองค์ประกอบใดที่มีการเปลี่ยนแปลงและตำแหน่งใดใน DOM นั้นจำเป็นต้องเปลี่ยนเพื่อให้ DOM เบราว์เซอร์ซิงค์กับ Reacts Virtual DOM

ในฐานะที่เป็นวิธีแก้ปัญหาเพียงแค่แนะนำkeyคุณลักษณะให้กับแต่ละliแท็ก นี่keyควรเป็นค่าที่ไม่ซ้ำกันของแต่ละองค์ประกอบ


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

@Chris ในกรณีนั้นทำไมมันถึงแจ้งเตือน?
นายกรัฐมนตรี

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

@Chris ในกรณีของการแก้ไขอาเรย์นั้นจะตอบโต้การแก้ไขดัชนีตามนั้นหากเราไม่ได้ให้กุญแจ อย่างไรก็ตามฉันคิดว่าการลบค่าใช้จ่ายเพิ่มเติมจาก React จะส่งผลกระทบต่อกระบวนการแสดงผล
นายกรัฐมนตรี

key={i}อีกครั้งตอบสนองโดยทั่วไปจะทำ ดังนั้นมันจึงขึ้นอยู่กับข้อมูลที่อาร์เรย์ของคุณมี ตัวอย่างเช่นหากคุณมีรายการ["Volvo", "Tesla"]ก็จะเห็นได้ชัดว่าวอลโว่ได้รับการระบุโดยคีย์0และเทสลาด้วย1- เพราะนั่นคือลำดับที่จะปรากฏในลูป ตอนนี้ถ้าคุณจัดลำดับอาร์เรย์ใหม่คีย์จะถูกสลับ สำหรับ React เนื่องจาก "object" 0ยังคงอยู่ที่ด้านบนจึงจะตีความการเปลี่ยนแปลงนี้ว่า "เปลี่ยนชื่อ" แทนที่จะเรียงลำดับใหม่ ปุ่มที่ถูกต้องที่นี่จะต้องมีในการสั่งซื้อแล้ว1 0คุณไม่ได้สั่งรันไทม์ตอนกลางใหม่เสมอ แต่เมื่อคุณทำมันจะเป็นความเสี่ยง
Chris

0
var TableRowItem = React.createClass({
  render: function() {

    var td = function() {
        return this.props.columns.map(function(c, i) {
          return <td key={i}>{this.props.data[c]}</td>;
        }, this);
      }.bind(this);

    return (
      <tr>{ td(this.props.item) }</tr>
    )
  }
});

นี่จะทำให้ปัญหาเกิดขึ้น


0

ฉันพบข้อความแสดงข้อผิดพลาดนี้เนื่องจาก<></>ถูกส่งคืนสำหรับบางรายการในอาร์เรย์เมื่อnullต้องส่งคืนแทน


-1

ฉันแก้ไขสิ่งนี้โดยใช้ Guid สำหรับแต่ละคีย์เช่นนี้: กำลังสร้าง Guid:

guid() {
    return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' +
        this.s4() + '-' + this.s4() + this.s4() + this.s4();
}

s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
}

จากนั้นกำหนดค่านี้ให้กับเครื่องหมาย:

{this.state.markers.map(marker => (
              <MapView.Marker
                  key={this.guid()}
                  coordinate={marker.coordinates}
                  title={marker.title}
              />
          ))}

2
การเพิ่มหมายเลขแบบสุ่มเป็นคีย์จะเป็นอันตราย! มันจะป้องกันการตอบสนองเพื่อตรวจจับการเปลี่ยนแปลงซึ่งเป็นจุดประสงค์ของคีย์
pihentagy

-1

โดยทั่วไปคุณไม่ควรใช้ดัชนีของอาร์เรย์เป็นคีย์เฉพาะ คุณสามารถใช้ a setTimeout(() => Date.now(),0)เพื่อตั้งค่าคีย์เฉพาะหรือuuid ที่ไม่เป็นอันตรายหรือวิธีอื่นใดที่จะสร้าง id เฉพาะ แต่ไม่ใช่ดัชนีของอาร์เรย์เป็น id เฉพาะ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.