प्रतिनिधि इंटरव्यू विषय

फ़्रंटएंड इंटरव्यू: React Keys स्टेट प्रिजर्वेशन और रीमाउंटिंग को कैसे नियंत्रित करती हैं?

फ्रंटएंडमध्यम
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक React पेज में एक एडिटेबल लिस्ट है जिसे उपयोगकर्ता सॉर्ट, फ़िल्टर और उसमें नया आइटम इंसर्ट कर सकते हैं। प्रत्येक पंक्ति एक स्थानीय ड्राफ्ट और एक्सपैंडेड स्टेट बनाए रखती है। यह पेज अलग-अलग उपयोगकर्ताओं के लिए डिटेल फॉर्म्स के बीच भी स्विच करता है। समझाएं कि keys कंपोनेंट पहचान और स्टेट प्रिजर्वेशन को कैसे प्रभावित करती हैं, ऐरे इंडेक्स या रैंडम वैल्यू बग्स का कारण क्यों बनती हैं, और कब key बदलना किसी सबट्री को रीमाउंट करने का सही तरीका है।

प्रश्न और लागू परिदृश्य

एक एडमिन पेज एक एडिटेबल यूज़र लिस्ट रेंडर करता है। प्रत्येक Row का अपना एक अनसबमिट किया हुआ इनपुट ड्राफ्ट और एक्सपैंडेड स्टेट होता है। यूज़र्स सबसे ऊपर एक रिकॉर्ड जोड़ सकते हैं, बीच के रिकॉर्ड को हटा सकते हैं, सॉर्ट कर सकते हैं और फ़िल्टर कर सकते हैं। लिस्ट के पास मौजूद एक डिटेल फॉर्म को पिछली यूज़र की स्थानीय स्टेट को साफ़ कर देना चाहिए जब भी userId बदलता है।

समझाएं:

  1. React कैसे तय करता है कि कोई कंपोनेंट लगातार होने वाले रेंडर्स के बीच वही कंपोनेंट है या नहीं।
  2. क्यों key={index} ड्राफ्ट या एक्सपैंडेड स्टेट को किसी अन्य रिकॉर्ड में ले जा सकता है।
  3. क्यों key={Math.random()} कंपोनेंट्स को बार-बार रीमाउंट करता है।
  4. कब एक स्थिर डोमेन ID को स्टेट बनाए रखनी चाहिए और कब key बदलने से सबट्री को रीसेट होना चाहिए।
  5. इंसर्शन, डिलीशन, सॉर्टिंग, फ़िल्टरिंग और एंटिटी स्विचिंग के दौरान इस व्यवहार को कैसे सत्यापित करें।

मार्च और मई 2026 में प्रकाशित React इंटरव्यू सामग्री में सीधे तौर पर keys, इंडेक्स keys, reconciliation और रीमाउंटिंग शामिल हैं। यद्यपि यह प्रश्न लिस्ट सिंटैक्स जैसा दिखता है, यह इस बात का परीक्षण करता है कि क्या कोई उम्मीदवार यह मॉडल कर सकता है कि कौन सी लॉजिकल एंटिटी स्टेट की मालिक है और उस मॉडल को कंपोनेंट सीमाओं और परीक्षणों के माध्यम से व्यक्त कर सकता है।

यह एक फ़्रंटएंड प्रश्न है क्योंकि इसकी मुख्य दक्षता React कंपोनेंट पहचान, स्टेट लाइफ़टाइम और DOM रीयूज़ है।

इंटरव्यूअर क्या मूल्यांकन कर रहा है

पहला, उम्मीदवार को पता होना चाहिए कि स्टेट स्वचालित रूप से किसी JSX टैग या डोमेन ऑब्जेक्ट से नहीं जुड़ी होती है। React स्टेट को रेंडर ट्री में एक स्थिति से जोड़ता है। एक पैरेंट के भीतर, एलिमेंट प्रकार और key यह निर्धारित करने में मदद करते हैं कि पुराने और नए चिल्ड्रन एक ही पहचान का प्रतिनिधित्व करते हैं या नहीं।

दूसरा, उम्मीदवार को री-रेंडर और रीमाउंट के बीच अंतर करना आना चाहिए। नए प्रॉप्स या पैरेंट अपडेट इसकी स्थानीय स्टेट को बनाए रखते हुए उसी पहचान को री-रेंडर कर सकते हैं। एक बदला हुआ कंपोनेंट प्रकार या key एक नई पहचान बनाती है, पुरानी सबट्री की स्थानीय स्टेट को नष्ट करती है, और इसके DOM को फिर से बना सकती है।

तीसरा, उम्मीदवार को डोमेन पहचान से keys प्राप्त करनी चाहिए। रिकॉर्ड बनाए जाने पर उत्पन्न और संग्रहीत डेटाबेस ID या UUID का आम तौर पर अर्थ होता है "यह अभी भी वही रिकॉर्ड है।" ऐरे स्थिति, वर्तमान टाइमस्टैम्प, या रेंडर के दौरान उत्पन्न कोई रैंडम वैल्यू ऐसा नहीं करती है।

चौथा, एक मजबूत उत्तर "कभी भी key न बदलें" को नियम नहीं बनाता है। जब कोई डिटेल फॉर्म यूज़र A से यूज़र B पर स्विच करता है, तो फॉर्म अलग-अलग डोमेन एंटिटीज़ का प्रतिनिधित्व कर सकते हैं। सही सीमा पर key={userId} Effects में अलग-अलग स्टेट वेरिएबल्स को साफ़ करने की तुलना में पूरी फॉर्म सबट्री को अधिक विश्वसनीय रूप से रीसेट कर सकता है।

अंत में, उम्मीदवार को रीमाउंटिंग की लागत का नाम देना चाहिए: फ़ोकस, स्क्रॉल स्थिति, अनसबमिट किया गया इनपुट और डिसेंडेंट स्टेट सभी खो सकते हैं। यदि किसी एंटिटी को फिर से चुने जाने पर उत्पाद को ड्राफ्ट को पुनर्स्थापित करना होगा, तो हटाए गए सबट्री में स्थानीय स्टेट पर निर्भर रहने के बजाय ड्राफ्ट को लिफ़्ट करें, इसे एंटिटी द्वारा स्टोर करें, या इसे बाहरी रूप से बनाए रखें।

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

  • क्या लिस्ट आइटम्स को इंसर्ट, डिलीट, सॉर्ट या फ़िल्टर कर सकती है? एक बार मेंबरशिप या क्रम बदलने पर, ऐरे इंडेक्स किसी डोमेन एंटिटी की स्थिर रूप से पहचान नहीं करता है।
  • क्या प्रत्येक पंक्ति React या ब्राउज़र DOM स्टेट की मालिक है? इनपुट्स, एक्सपेंशन स्टेट, एनिमेशन और अनियंत्रित फ़ील्ड्स गलत रीयूज़ को तेज़ी से उजागर करते हैं।
  • क्या डेटा के पास अपने सिबलिंग्स के बीच एक अद्वितीय स्थिर ID है? Keys को सिबलिंग विशिष्टता की आवश्यकता होती है, न कि वैश्विक विशिष्टता की।
  • क्या किसी एंटिटी स्विच को अपना ड्राफ्ट छोड़ देना चाहिए या पुनर्स्थापित करना चाहिए? त्यागना key बदलने के अनुकूल है; पुनर्स्थापना के लिए लंबे समय तक रहने वाली स्टेट लेयर की आवश्यकता होती है।
  • क्या पूरी सबट्री को रीसेट होना चाहिए या केवल एक फ़ील्ड को? पूर्ण पहचान रीसेट के लिए key का उपयोग करें; आंशिक समायोजन के लिए कंट्रोल्ड स्टेट या स्पष्ट डेटा अपडेट को प्राथमिकता दें।
  • ID कब उत्पन्न होती है? एक स्थानीय रिकॉर्ड बनाए जाने पर UUID प्राप्त कर सकता है और इसे रख सकता है। प्रत्येक रेंडर पर नया न बनाएं।

30-सेकंड का उत्तर ढांचा

"React स्टेट को रेंडर ट्री में स्थितियों से जोड़ता है। एक ही पैरेंट के तहत, कंपोनेंट प्रकार और key React को यह निर्धारित करने में मदद करते हैं कि पुराने और नए नोड्स की समान पहचान है या नहीं। एक स्थिर key पंक्ति की स्टेट को डोमेन रिकॉर्ड का अनुसरण करने देती है, भले ही वह स्थानांतरित हो जाए। ऐरे इंडेक्स के साथ, इंसर्शन या सॉर्टिंग उसी स्लॉट में एक अलग रिकॉर्ड डाल सकती है, इसलिए एक स्थानीय ड्राफ्ट गलत पंक्ति में जा सकता है। एक रैंडम key कभी भी पिछले रेंडर से मेल नहीं खाती है, इसलिए React बार-बार कंपोनेंट और DOM को फिर से बनाता है।

लिस्ट्स को डेटा से एक स्थिर ID का उपयोग करना चाहिए। यदि यूज़र A के डिटेल फॉर्म से यूज़र B पर स्विच करने पर सभी स्थानीय स्टेट को साफ़ करना होगा, तो मैं यह बताने के लिए कि यह एक नई एंटिटी है, फॉर्म-सबट्री सीमा पर key={userId} लगाऊंगा। यदि प्रत्येक यूज़र के ड्राफ्ट को बनाए रखना है, तो मैं पहचान की सीमा को बनाए रखते हुए ड्राफ्ट्स को लिफ़्ट करूंगा और उन्हें userId द्वारा स्टोर करूंगा। मैं यह साबित करने के लिए इंसर्शन, डिलीशन, रीऑर्डरिंग, फ़िल्टरिंग, समान-ID री-रेंडर्स और अलग-अलग-ID स्विच को सत्यापित करूंगा कि स्टेट इच्छित एंटिटी का अनुसरण करती है।"

चरण-दर-चरण गहन विश्लेषण

चरण 1: कंपोनेंट पहचान मॉडल बनाएं।

एक उपयोगी साक्षात्कार मॉडल है:

पुराने और नए रेंडर के बीच संबंधविशिष्ट परिणाम
समान पैरेंट, समान कंपोनेंट प्रकार, समान keyउस पहचान की स्थानीय स्टेट बनाए रखें; कंपोनेंट री-रेंडर हो सकता है
समान पैरेंट, समान प्रकार, भिन्न keyपुरानी पहचान हटाएं, एक नई पहचान माउंट करें, और सबट्री स्टेट रीसेट करें
समान स्थिति, भिन्न कंपोनेंट प्रकारपुरानी सबट्री बदलें और स्टेट रीसेट करें
बिना किसी स्पष्ट key वाली लिस्टस्थितिगत मिलान पर वापस जाएं, जो डायनेमिक लिस्ट्स के लिए असुरक्षित है

key कंपोनेंट को दिया जाने वाला कोई साधारण प्रॉप नहीं है। यह एक React संकेत है। यदि Row को डोमेन ID की भी आवश्यकता है, तो एक अलग प्रॉप पास करें जैसे कि rowId={item.id}

एक key केवल अपने वर्तमान पैरेंट के भीतर ही पहचान को परिभाषित करती है। दो अलग-अलग सूचियों में दोनों में key="user-42" हो सकता है, जबकि एक सूची के अंदर सिबलिंग्स में डुप्लिकेट keys नहीं होनी चाहिए।

चरण 2: एडिटेबल लिस्ट के साथ इंडेक्स-key बग को पुनरुत्पादित करें।

गलत कार्यान्वयन:

tsx
function UserList({ users }: { users: User[] }) {
  return users.map((user, index) => (
    <EditableRow key={index} user={user} />
  ))
}

मान लें कि प्रारंभिक क्रम [Alice, Bob] है। इंडेक्स 0 पर मौजूद EditableRow ऐलिस का ड्राफ्ट संग्रहीत करता है। सबसे ऊपर ज़ो को डालें, जिससे [Zoe, Alice, Bob] बनता है। React key 0 वाली पुरानी पंक्ति को इंडेक्स 0 पर मौजूद नए आइटम से मिला सकता है, इसलिए ऐलिस से संबंधित स्टेट ज़ो की पंक्ति में दिखाई दे सकती है। key 1 पर मौजूद स्टेट इसी तरह बॉब से ऐलिस में स्थानांतरित हो सकती है।

समस्या यह नहीं है कि इंडेक्स एक संख्या है। इंडेक्स एक स्लॉट की पहचान करता है जबकि उत्पाद को एक यूज़र की पहचान करने की आवश्यकता होती है। डिलीशन, सॉर्टिंग और फ़िल्टरिंग सभी स्लॉट्स और एंटिटीज़ के बीच मैपिंग को बदलते हैं।

सही कार्यान्वयन:

tsx
function UserList({ users }: { users: User[] }) {
  return users.map((user) => (
    <EditableRow key={user.id} rowId={user.id} user={user} />
  ))
}

ज़ो को शामिल किए जाने के बाद, ऐलिस के पास अभी भी ऐलिस की ID है। वह इंडेक्स 0 से इंडेक्स 1 पर जा सकती है, और React ऐलिस की कंपोनेंट स्टेट को ऐलिस से मिलाना जारी रख सकता है।

यदि एक रिकॉर्ड कई सिबलिंग नोड्स लौटाता है, तो छोटा Fragment सिंटैक्स key नहीं ले सकता है। एक स्पष्ट Fragment का उपयोग करें:

tsx
import { Fragment } from 'react'

users.map((user) => (
  <Fragment key={user.id}>
    <UserHeading user={user} />
    <EditableRow user={user} />
  </Fragment>
))

चरण 3: रेंडर के दौरान बनाने के बजाय एक स्थिर key चुनें।

एक व्यावहारिक प्राथमिकता क्रम है:

  1. बैकएंड या डेटाबेस से एक स्थिर रिकॉर्ड ID।
  2. डेटा से पहले से जुड़ा एक विशिष्ट पहचानकर्ता और उसके डोमेन लाइफ़टाइम के दौरान अपरिवर्तित।
  3. केवल-स्थानीय नए रिकॉर्ड के लिए, रिकॉर्ड बनाने वाले इवेंट में उत्पन्न और रिकॉर्ड के साथ सहेजा गया एक UUID।
  4. एक कंपोजिट key केवल तभी जब उसके फ़ील्ड्स वास्तव में एक इम्यूटेबल, सिबलिंग-यूनिक डोमेन पहचान बनाते हैं।

निम्नलिखित प्रत्येक रेंडर पर एक नई पहचान बनाता है:

tsx
<EditableRow key={Math.random()} user={user} />

यह कोई सामान्य री-रेंडर नहीं है। React पुरानी पंक्ति को हटा देता है और एक नई पंक्ति माउंट करता है। स्थानीय स्टेट और यूज़र इनपुट खो जाते हैं, और DOM फिर से बन जाता है। Date.now() या रेंडर के दौरान crypto.randomUUID() को कॉल करने में भी यही समस्या है। आइटम निर्माण के दौरान एक बार जेनरेट होने और स्टोर होने पर UUID ठीक है, न कि आइटम को रेंडर करते समय जेनरेट होने पर।

एक ऐरे इंडेक्स केवल एक संकीर्ण अनुबंध के तहत स्वीकार्य है: सदस्यता और क्रम सूची के पूरे जीवनकाल के लिए तय रहते हैं, कोई इंसर्शन, डिलीशन, फ़िल्टरिंग या रीऑर्डरिंग नहीं है, स्थिति ही पहचान है, और किसी भी स्टेट को डोमेन एंटिटी का अनुसरण नहीं करना चाहिए। गतिशील व्यावसायिक डेटा को उन मान्यताओं पर भरोसा करने के बजाय एक वास्तविक ID प्राप्त करनी चाहिए।

चरण 4: यह व्यक्त करने के लिए एक key का उपयोग करें कि "यह एक अलग फॉर्म है।"

डिटेल पेजों पर एक सामान्य रूप से आज़माया गया समाधान है:

tsx
function Profile({ userId }: { userId: string }) {
  const [comment, setComment] = useState('')

  useEffect(() => {
    setComment('')
  }, [userId])

  return <CommentForm value={comment} onChange={setComment} />
}

यह पहले पुराने कमेंट के साथ ट्री को रेंडर करता है और फिर Effect चलने के बाद दूसरा रेंडर ट्रिगर करता है। इससे भी महत्वपूर्ण बात यह है कि एक गहरे डिटेल पेज में अटैचमेंट्स, वैलिडेशन एरर्स और नेस्टेड फॉर्म स्टेट भी हो सकती है। एक comment वेरिएबल को साफ़ करना यह गारंटी नहीं देता है कि पूरी सबट्री रीसेट हो जाएगी।

यदि उत्पाद प्रत्येक यूज़र के फॉर्म को एक अलग एंटिटी के रूप में परिभाषित करता है, तो key को पहचान की सीमा पर रखें:

tsx
function ProfilePage({ userId }: { userId: string }) {
  return <ProfileForm key={userId} userId={userId} />
}

जब userId बदलता है, तो React नए ProfileForm को एक अलग पहचान के रूप में मानता है और इसकी स्थानीय स्टेट और सभी डिसेंडेंट स्टेट को रीसेट करता है। जब असंबंधित पैरेंट स्टेट समान userId के साथ री-रेंडर का कारण बनती है, तो key स्थिर रहती है और स्थानीय स्टेट संरक्षित रहती है।

Key को सबसे छोटी पूर्ण सीमा पर रखें जिसे रीसेट किया जाना चाहिए। पूरे पेज को कीयिंग करने से नेविगेशन, महंगे डिस्प्ले और असंबंधित स्क्रॉल स्थिति भी फिर से बन जाती है। एक इनपुट को कीयिंग करने से उसी फॉर्म की अन्य स्टेट पीछे छूट सकती है।

चरण 5: रीमाउंट चुनने से पहले तय करें कि उत्पाद को क्या संरक्षित करना चाहिए।

"एंटिटी स्विच करें" का स्वचालित रूप से अर्थ "ड्राफ्ट छोड़ें" नहीं है। एक निर्णय तालिका का उपयोग करें:

उत्पाद सिमेंटिक्सअनुशंसित स्टेट डिज़ाइन
किसी अन्य एंटिटी को पूरी तरह से नया फॉर्म प्राप्त होना चाहिएफॉर्म-सबट्री key के रूप में एंटिटी ID का उपयोग करें
किसी एंटिटी पर वापस लौटने पर उसके ड्राफ्ट को पुनर्स्थापित करना चाहिएपहचान keys रखें; ड्राफ्ट्स को लिफ़्ट करें और उन्हें ID द्वारा स्टोर करें
एक पेज रीफ़्रेश को ड्राफ्ट्स को भी पुनर्स्थापित करना चाहिएसमाप्ति और क्लीनअप नियमों के साथ उन्हें बाहरी रूप से बनाए रखें
बाकी को बनाए रखते हुए एक फ़ील्ड रीसेट करेंकंट्रोल्ड स्टेट या स्पष्ट अपडेट का उपयोग करें; सबट्री को रीमाउंट न करें
प्रॉप्स केवल एक व्युत्पन्न प्रदर्शन मान बदलते हैंस्टेट में कॉपी करने के बजाय रेंडर के दौरान प्रॉप्स से गणना करें

Keys पहचान सीमाओं को परिभाषित करती हैं; वे दीर्घकालिक दृढ़ता प्रदान नहीं करती हैं। एक बार स्टेट को drafts[userId] में लिफ़्ट कर दिए जाने के बाद, एक फॉर्म सबट्री अनमाउंट हो सकती है जबकि उसका ड्राफ्ट पैरेंट में रहता है। उस यूज़र को फिर से चुनने पर संग्रहीत मान के साथ फॉर्म को इनिशियलाइज़ या नियंत्रित किया जा सकता है।

चरण 6: आकस्मिक रीसेट के अन्य कारणों को पहचानें।

सही keys के साथ भी, कंपोनेंट प्रकार बदलने से स्टेट रीसेट हो जाती है। उसी ट्री स्थिति को ProfileForm से LoginPrompt में स्विच करने से सबट्री बदल जाती है।

एक और आम गलती किसी कंपोनेंट को दूसरे कंपोनेंट के अंदर परिभाषित करना है:

tsx
function ProfilePage() {
  function ProfileForm() {
    const [name, setName] = useState('')
    return <input value={name} onChange={(event) => setName(event.target.value)} />
  }

  return <ProfileForm />
}

प्रत्येक ProfilePage रेंडर एक नया ProfileForm फ़ंक्शन ऑब्जेक्ट बनाता है। React एक अलग कंपोनेंट प्रकार देखता है और अप्रत्याशित रूप से इनपुट स्टेट को रीसेट करता है। कंपोनेंट परिभाषाएं शीर्ष स्तर पर रहनी चाहिए। केवल keys पर केंद्रित उत्तर इस संबंधित पहचान बग को छोड़ सकता है।

चरण 7: वर्चुअलाइज्ड लिस्ट्स पर समान पहचान नियम लागू करें।

एक वर्चुअलाइज्ड सूची बार-बार दृश्यमान स्लॉट्स की एक छोटी संख्या का पुन: उपयोग करती है। यदि लाइब्रेरी एक itemKey स्वीकार करती है, तो विंडो इंडेक्स के बजाय डोमेन एंटिटी ID लौटाएं। अन्यथा, स्क्रॉलिंग या रीऑर्डरिंग एक एंटिटी को दूसरे स्लॉट से स्टेट इनहेरिट करने की अनुमति दे सकती है।

बड़ी सूचियों के लिए, इससे भी अधिक सुरक्षित डिज़ाइन अक्सर पंक्तियों के अंदर गैर-स्थायी व्यावसायिक स्टेट को कम करता है। रिकॉर्ड ID द्वारा सूची के ऊपर एडिट ड्राफ्ट्स स्टोर करें और प्रत्येक पंक्ति को अपनी एंटिटी का ड्राफ्ट पढ़ने दें। फिर एक वर्चुअलाइजेशन लाइब्रेरी व्यावसायिक डेटा को हटाए बिना ऑफ़-स्क्रीन पंक्तियों को अनमाउंट कर सकती है।

चरण 8: केवल रेंडर किए गए टेक्स्ट का ही नहीं, बल्कि स्टेट के स्वामित्व का सत्यापन करें।

प्रत्येक परीक्षण के लिए, बताएं कि किस ID के पास स्टेट होनी चाहिए:

ऑपरेशनअपेक्षित परिणाम
ऐलिस में एक ड्राफ्ट टाइप करें, फिर सबसे ऊपर ज़ो को डालेंड्राफ्ट अभी भी केवल ऐलिस का है
बीच का आइटम हटाएंअन्य पंक्तियों की विस्तारित और इनपुट स्टेट माइग्रेट नहीं होती है
अवरोही क्रम में सॉर्ट करें, फिर मूल क्रम को पुनर्स्थापित करेंप्रत्येक पंक्ति की स्टेट उसकी रिकॉर्ड ID का अनुसरण करना जारी रखती है
ऐलिस को फ़िल्टर करके हटा दें, फिर फ़िल्टर को पुनर्स्थापित करेंअनमाउंट के बाद पंक्ति-स्थानीय स्टेट खो जाती है; यदि आवश्यक हो तो लिफ़्टेड ड्राफ्ट स्टोर से पुनर्स्थापित करें
समान userId के साथ पैरेंट री-रेंडर ट्रिगर करेंफॉर्म की स्थानीय स्टेट संरक्षित है
यूज़र A से यूज़र B पर स्विच करेंuserId द्वारा कीयड फॉर्म पूरी तरह से रीसेट हो जाता है
अस्थायी रूप से एक रैंडम key का उपयोग करें और पैरेंट री-रेंडर ट्रिगर करेंइनपुट हानि और DOM पुनर्निर्माण विफलता तंत्र को प्रदर्शित करते हैं
डुप्लिकेट ID प्राप्त करेंसिबलिंग key संघर्षों से बचने के लिए डेटा सीमा पर चेतावनी दें या अस्वीकार करें

परीक्षणों में फ़ोकस और अनकंट्रोल्ड इनपुट्स को भी शामिल किया जाना चाहिए। एक गलत key React स्टेट को सही दिखा सकती है जबकि ब्राउज़र-धारित DOM मान या फ़ोकस गलत रिकॉर्ड पर चले जाते हैं। स्वीकृति मानदंड को केवल रेंडर गणनाओं के बजाय उपयोगकर्ताओं को दिखाई देने वाली एंटिटी निरंतरता का वर्णन करना चाहिए।

उच्च-गुणवत्ता वाला नमूना उत्तर

"मैं key को कंपोनेंट पहचान के हिस्से के रूप में मानता हूं, न कि केवल एक ऐसे एट्रिब्यूट के रूप में जो केवल कंसोल चेतावनी को हटाता है। React स्टेट को रेंडर-ट्री स्थितियों से जोड़ता है। एक पैरेंट के तहत, समान कंपोनेंट प्रकार और key आमतौर पर समान पहचान का प्रतिनिधित्व करते हैं, इसलिए प्रॉप अपडेट या मूवमेंट स्टेट को बनाए रखते हुए री-रेंडर कर सकते हैं। एक बदला हुआ प्रकार या key एक नई पहचान का प्रतिनिधित्व करता है: React पुरानी सबट्री को हटा देता है और एक नई सबट्री को माउंट करता है।

एक एडिटेबल सूची में, इंडेक्स स्थिति की पहचान करता है, उपयोगकर्ता की नहीं। यदि [Alice, Bob] keys 0 और 1 का उपयोग करता है और ज़ो को सबसे ऊपर डाला जाता है, तो key 0 वाली पुरानी पंक्ति अब ज़ो को रेंडर कर सकती है, इसलिए ऐलिस का ड्राफ्ट या विस्तारित स्टेट ज़ो के तहत दिखाई दे सकती है। मैं user.id का उपयोग करूंगा, जो ऐलिस की पहचान को स्थिर रखता है जब वह इंडेक्स 0 से इंडेक्स 1 पर जाती है। रेंडर के दौरान उत्पन्न एक रैंडम key, टाइमस्टैम्प, या UUID कभी भी पिछले रेंडर से मेल नहीं खाता है, इसलिए React बार-बार कंपोनेंट्स और DOM को फिर से बनाता है और इनपुट खो देता है। Keys को केवल सिबलिंग्स के बीच अद्वितीय होना चाहिए, और चाइल्ड को प्रॉप के रूप में key प्राप्त नहीं होता है।

डिटेल फॉर्म उत्पाद सिमेंटिक्स पर निर्भर करता है। यदि यूज़र A से यूज़र B पर स्विच करने पर पूरे फॉर्म को साफ़ करना होगा, तो मैं key={userId} को ProfileForm सीमा पर रखूंगा ताकि कई Effects में फ़ील्ड्स को साफ़ करने के बजाय सभी डिसेंडेंट स्टेट एक साथ रीसेट हो जाएं। यदि A पर लौटने पर एक ड्राफ्ट को पुनर्स्थापित करना होगा, तो मैं userId द्वारा पहचान को अलग रखूंगा लेकिन ड्राफ्ट्स को userId द्वारा लिफ़्ट या बाहरी रूप से बनाए रखूंगा।

अंत में, मैं शीर्ष पर इंसर्शन, डिलीशन, रीऑर्डरिंग, फ़िल्टरिंग, समान-ID री-रेंडर्स और अलग-अलग-ID स्विच का परीक्षण करूंगा। मैं जाँचूँगा कि इनपुट, एक्सपेंशन स्टेट, फ़ोकस और ड्राफ्ट सभी इच्छित डोमेन ID का अनुसरण करते हैं। यह साबित करता है कि key केवल पेज को अपडेट करने की अनुमति देने के बजाय सही पहचान का मॉडल बनाती है।"

सामान्य गलतियाँ

  • Keys को केवल प्रदर्शन अनुकूलन के रूप में समझाना → मुख्य मुद्दा चाइल्ड पहचान और स्टेट का स्वामित्व है → पहले स्टेट मिसमैच समझाएं, फिर अपडेट लागत।
  • प्रत्येक सूची के लिए ऐरे इंडेक्स का उपयोग करना → इंसर्शन, डिलीशन, रीऑर्डरिंग और फ़िल्टरिंग स्लॉट-टू-एंटिटी मैपिंग को बदलते हैं → डेटा से एक स्थिर ID का उपयोग करें।
  • रेंडर के दौरान एक UUID या रैंडम वैल्यू जेनरेट करना → Key हर बार बदलती है और कंपोनेंट्स और DOM को फिर से बनाती है → आइटम बनाए जाने पर ID जेनरेट और स्टोर करें।
  • Keys को विश्व स्तर पर अद्वितीय होने की आवश्यकता होना → React को सिबलिंग्स के बीच विशिष्टता की आवश्यकता होती है → वर्तमान पैरेंट और सूची के भीतर संघर्षों का मूल्यांकन करें।
  • चाइल्ड में props.key को पढ़ना → React key को एक सामान्य प्रॉप के रूप में पास नहीं करता है → एक अलग rowId या userId पास करें।
  • Effects में एक जटिल फॉर्म को फ़ील्ड-दर-फ़ील्ड साफ़ करना → यह पुरानी स्टेट को रेंडर करता है, एक और रेंडर जोड़ता है, और डिसेंडेंट स्टेट को मिस कर सकता है → सही पहचान सीमा पर key बदलें।
  • एक फ़ील्ड को साफ़ करने के लिए पूरे पेज को रीमाउंट करना → यह फ़ोकस, स्क्रॉल और असंबंधित स्टेट खो देता है → Key सीमा को संकीर्ण करें या फ़ील्ड को स्पष्ट रूप से अपडेट करें।
  • यह मानना कि एक स्थिर key फ़िल्टरिंग के बाद स्टेट को बनाए रखती है → एक फ़िल्टर किया गया कंपोनेंट अनमाउंट हो सकता है → पुनर्स्थापना की आवश्यकता होने पर स्टेट को लिफ़्ट या बनाए रखें।

फॉलो-अप प्रश्न

फॉलो-अप 1: जब डेटा में कोई बैकएंड ID नहीं होती है तो किस key का उपयोग किया जाना चाहिए?

उस इवेंट में एक ID जेनरेट करें, जैसे कि एक UUID, जो स्थानीय रिकॉर्ड बनाती है और इसे रिकॉर्ड फ़ील्ड के रूप में स्टोर करती है। हर बाद का रेंडर उसी ID को पढ़ता है। डोमेन फ़ील्ड्स का एक अपरिवर्तनीय, सिबलिंग-अद्वितीय संयोजन काम कर सकता है यदि वह अनुबंध सिद्ध हो। map रेंडर के अंदर अस्थायी रूप से key जेनरेट न करें।

फॉलो-अप 2: Key के रूप में ऐरे इंडेक्स कब स्वीकार्य है?

यह अपेक्षाकृत सुरक्षित केवल तभी है जब सदस्यता और क्रम सूची के पूरे जीवनकाल के लिए तय रहते हैं, कोई इंसर्शन, डिलीशन, फ़िल्टरिंग या रीऑर्डरिंग नहीं होती है, और स्थिति ही पहचान होती है। एक निश्चित स्थिर डिस्प्ले उस सीमा को संतुष्ट कर सकता है। गतिशील व्यावसायिक डेटा को स्थिर एंटिटी IDs का उपयोग करना चाहिए क्योंकि सॉर्टिंग या संपादन तुरंत इंडेक्स मान्यताओं को अमान्य कर देता है।

फॉलो-अप 3: यदि userId बदलने पर केवल एक फ़ील्ड को साफ़ करना हो, तो क्या पूरी फॉर्म key बदलनी चाहिए?

ज़रूरी नहीं। एक key पूरी सबट्री को रीसेट करती है। यदि अन्य स्थानीय स्टेट को बने रहना चाहिए, तो एक नियंत्रित फ़ील्ड का उपयोग करें, सीधे प्रॉप्स से एक मान प्राप्त करें, या इसे एक स्पष्ट डेटा अपडेट पथ में समायोजित करें। Key रीसेट केवल तभी चुनें जब पूरी सबट्री किसी अन्य एंटिटी का प्रतिनिधित्व करती हो और उसकी सभी स्थानीय स्टेट को फिर से शुरू होना चाहिए।

फॉलो-अप 4: Key बदलने के बाद ड्राफ्ट को कैसे पुनर्स्थापित किया जा सकता है?

ड्राफ्ट्स को पैरेंट में लिफ़्ट करें, उदाहरण के लिए drafts[userId] के रूप में, या समाप्ति और क्लीनअप नियमों के साथ उन्हें बाहरी रूप से बनाए रखें। फॉर्म key को userId पर आधारित रखें ताकि विभिन्न उपयोगकर्ता स्थानीय स्टेट साझा न करें। एक नया माउंट किया गया फॉर्म संबंधित संग्रहीत ड्राफ्ट से अपना प्रारंभिक मान पढ़ता है। पहचान अलगाव और ड्राफ्ट दृढ़ता अलग-अलग जिम्मेदारियां हैं।

फॉलो-अप 5: क्या एक वर्चुअलाइज्ड सूची को अभी भी स्थिर keys की आवश्यकता होती है जब वह पहले से ही DOM का पुन: उपयोग करती है?

हाँ। वर्चुअलाइजेशन दृश्यमान नोड्स की संख्या को नियंत्रित करता है; यह डोमेन पहचान को फिर से परिभाषित नहीं करता है। यदि लाइब्रेरी itemKey को उजागर करती है, तो रिकॉर्ड ID लौटाएं। अनमाउंटिंग से बचने के लिए संपादन स्टेट को पंक्तियों के ऊपर ID द्वारा भी रहना चाहिए, अन्यथा जब कोई पंक्ति विंडो से बाहर स्क्रॉल होती है तो यह गायब हो जाएगी।

सार्वजनिक स्रोत

संबंधित प्रश्न