Menu

React useId Hook'u: Etiketler ve ARIA için Benzersiz ID

useId her bileşen örneği için benzersiz, sabit bir id döndürür; böylece bir etiket, bir input ve bir aria-describedby ipucu, bileşen birçok kez görünse bile birbirini gösterebilir. Math.random ve sayaçların sunucu tarafı render'da neden bozulduğunu ve useId'nin neden liste key'leri için olmadığını öğren.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

useId, bir bileşenin her örneği için benzersiz bir id ve her render'da aynı id'yi döndürür. Bileşen bir sayfada birden fazla kez görünebildiğinde bir <label>'ı kendi <input>'una ya da bir input'u aria-describedby aracılığıyla ipucuna bağlamak için onu kullan.

Aynı bileşen iki kez render edilir ve her alanın altında yazdırılan iki farklı id alır. "Confirm password" metnine tıkla; odak ikinci input'a atlar, çünkü htmlFor'u yalnızca o input'un id'siyle eşleşir. useId() yerine sabit id="password" yaz; iki etiket de ilk input'u gösterir.

Sözdizimi

const id = useId();

useId argüman almaz ve bir metin döndürür. Onu her hook gibi bileşenin en üst düzeyinde çağır. Tam biçimi içseldir ve sürümler arasında değişmiştir: React 18 :r1: üretiyordu; React 19.2 ise ilk olarak tarayıcıda render edilen bir bileşen için _r_1_, sunucuda render edilen bir bileşen için de ağaç konumundan oluşturulmuş, _R_ ile başlayan bir id üretir. Onu asla ayrıştırma ya da şekline güvenme.

Neden Math.random ya da bir sayaç değil

Erişilebilirlik için id'ler, sunucunun gönderdiği HTML ile React'in tarayıcıda oluşturduğu ağaç arasında eşleşmelidir. Bir id üretmenin iki bariz yolu da bu testte başarısız olur.

// Changes on every render, and differs between server and browser
const id = 'field-' + Math.random().toString(36).slice(2);

// The server's counter keeps growing across requests, the browser starts at 0
let nextId = 0;
const id = 'field-' + nextId++;

Sunucu tarafı render ile (Next.js, React Router framework modu, herhangi bir hydrateRoot kurulumu) sunucu HTML'e id="field-4817" yazdırır, tarayıcının ilk render'ı field-0 hesaplar ve React bir hydration uyuşmazlığı bildirir. useId, id'yi bileşenin ağaçtaki konumundan oluşturur; bu da iki tarafta aynıdır.

Sunucu olmasa bile render sırasında oluşturulan bir id her render'da değişebilir. Bu örnek farkı hiçbir sunucu olmadan gösteriyor:

Düğmeye birkaç kez tıkla. useId değeri yerinde kalırken sayaç id'si her render'da tırmanır; bu yüzden eski id'yi gösteren her şey (bir aria-describedby, bir etiket) artık hiçbir şeyi göstermez. Sayacı useState(() => nextId++) ile sarmak yeniden render'ları düzeltirdi ama sunucu uyuşmazlığını düzeltmezdi.

Tek çağrıdan birkaç id

Birkaç alanı olan bir bileşenin birkaç useId çağrısına ihtiyacı yoktur. Bir taban üret ve her öğe için bir sonek ekle.

E-posta alanına @ içermeyen bir sözcük yaz: hata görünür ve input'un aria-describedby'ı onu gösterir, böylece bir ekran okuyucu input odaklandığında hatayı okur. App içinde <SignupForm />'u iki kez render et; her kopya kendi taban id'sini alır.

Liste key'leri için değil

Key'ler ve id'ler farklı sorunları çözer. Bir key, render'lar arasında hangi öğenin hangisi olduğunu React'e söyler, bu yüzden veriden gelmelidir. useId bileşen örneği başına bir id verir ve onu map içinde çağıramazsın.

// Wrong: breaks the rules of hooks, and the key is unrelated to the item
{todos.map((todo) => <Todo key={useId()} todo={todo} />)}

// Right: the key comes from the data
{todos.map((todo) => <Todo key={todo.id} todo={todo} />)}

Verinin id'si yoksa öğe oluşturulduğunda bir tane oluştur (onu ekleyen olay işleyicisinde crypto.randomUUID()), render sırasında değil. Listeler ve key'ler sayfası key'in neden öğesiyle kalması gerektiğini anlatıyor.

Bir sayfada birkaç React kökü

Aynı sayfada iki ayrı React uygulaması render edilirse id'leri çakışabilir. Her köke bir önek ver:

createRoot(document.getElementById('cart'), { identifierPrefix: 'cart-' });
createRoot(document.getElementById('chat'), { identifierPrefix: 'chat-' });

Sunucu tarafı render ile, iki tarafın da aynı id'leri üretmesi için sunucu renderer'ına ve hydrateRoot'a aynı identifierPrefix'i aktar.

Yaygın hatalar

Sunucuda ve tarayıcıda farklı bir ağaç render etmek. useId bileşenin konumuna bağlıdır, bu yüzden bir alanın üstündeki typeof window === 'undefined' ? <A /> : <B /> gibi bir dal id'leri iki render arasında kaydırabilir. Hydration sırasında ağacı aynı tut ve ondan sonra, bir efektte geçiş yap.

Öğeyi id'siyle aramak. document.getElementById(id) çalışır, ama bir ref, bir DOM düğümüne ulaşmanın React yoludur ve hiç id gerektirmez.

Onu rastgele bir değer olarak kullanmak. Id uygulama içinde benzersizdir, rastgele değildir ve ağaçtan tahmin edilebilir. Onu güvenlik token'ları, önbellek anahtarları ya da oturumlar arasında saklanan herhangi bir şey için kullanma.

Ne zaman kullanılmalı

Yeniden kullanılabilir bir bileşenin bir id özelliğine ihtiyacı olduğunda useId kullan: birçok kez kullanılan bir bileşenden oluşturulmuş form alanları, aria-describedby ile bağlanmış bir tooltip, aria-labelledby içeren bir diyalog, aria-controls içeren sekmeler. Bir id yalnızca bir etiketi input'una bağlıyorsa id'yi atlayıp input'u etiketin içine de koyabilirsin (<label>Name <input /></label>); öğeler iç içe konamadığında useId kullan.

Sıkça Sorulan Sorular

React'te useId ne yapar?

O bileşen örneğine özgü olan ve her render'da aynı kalan bir metin döndürür. Onu öğeleri id ile bağlamak için kullanırsın: bir etikette htmlFor, bir input'ta aria-describedby, bir diyalogda aria-labelledby.

Id'ler için neden Math.random() ya da bir sayaç kullanılmaz?

Sunucuda ve tarayıcıda farklı değerler verirler, bu yüzden sunucuda render edilmiş bir sayfa ile hydrate edilmiş sürümü uyuşmaz ve React bir hydration uyuşmazlığı bildirir. Math.random() ayrıca her render'da değişir. useId id'yi bileşenin ağaçtaki konumundan türetir; bu da iki yerde aynıdır.

useId'yi bir listedeki key'ler için kullanabilir miyim?

Hayır. Bir key, React'in aynı öğeyi render'lar arasında eşleştirebilmesi için verinden gelmelidir. useId bileşen başına bir kez çağrılır ve onu map içinde çağırmak zaten hook kurallarını çiğner. Öğenin kendi id'sini kullan.

Tek bir useId çağrısından birkaç id nasıl alınır?

useId'yi bir kez çağır ve sonekler ekle: ${id}-name, ${id}-email. Taban benzersizdir, bu yüzden sonekli metinler de benzersizdir.

useId'den gelen id'yi bir CSS seçicisinde kullanabilir miyim?

Bundan kaçın. Id, DOM'daki öğeleri bağlamak içindir ve tam biçimi React sürümleri arasında değişmiş bir iç ayrıntıdır. Bir sınıfla stillendir ve öğeleri querySelector yerine bir ref ile bul.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA