use - This feature is available in the latest Canary

Test Ortamı (Canary)

use API şu anda sadece React’ın Test Ortamı ve deneysel kanallarında mevcuttur. React’in yayın kanalları hakkında daha fazla bilgi edinmek için buraya göz atın.

use, Promise veya context gibi bir kaynağın değerini okumanıza olanak sağlayan bir React API’ıdır.

const value = use(resource);

Referans

use(resource)

Promise veya context gibi kaynakların değerini okumak için bileşeninizde use API’ını çağırabilirsiniz.

import { use } from 'react';

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...

Diğer React Hook’ların aksine, Döngülerin ve if gibi koşullu ifadeler içerisinde use kullanılabilir. Diğer React Hook’lar gibi, use kullanan fonksiyon bir Bileşen veya Hook olmalıdır.

Bir Pomise ile çağırıldığında; use API, Suspense ve hata sınırları ile entegre olur. use’a iletilen Promise beklenirken, use çağrısı yapan bileşen askıya alınır. Eğer use çağrısı yapan bileşen Suspense içerisine alınırsa yedek görünüm görüntülenecektir. Promise çözümlendiğinde ise; Suspense yedek görünümü, use API’ı tarafından döndürülen değerleri kullanarak oluşturulan bileşenler ile yer değiştirir. Eğer use’a iletilen Promise reddedilir ise, en yakındaki Hata Sınırının yedek görünümü görüntülenecektir.

Aşağıda daha fazla örnek görebilirsiniz.

Parametreler

  • resource: Bu, bir değeri okumak istediğiniz verinin kaynağıdır. Kaynak, Promise ya da context olabilir.

Dönüş Değerleri

use API, Promise ya da context gibi bir kaynaktan çözümlenen veriyi döndürür.

Önemli Hususlar

  • use API, bir bileşen veya bir hook’un içerisinde çağırılmak zorundadır..
  • Bir Sunucu Bileşeni içerisinde veri çekilirken, use yerine async ve await kullanmayı tercih edin. async ve await, oluşturma işlemini await ifadesinin çağırıldığı noktadan devam ettirirken; use, veri çözümlendikten sonra bileşeni yeniden oluşturur.
  • Sunucu Bileşeni içerisinde Promise oluşturup İstemci Bileşeni içerisine aktarmak yerine Promise’i İstemci Bileşeni içerisinde oluşturmayı tercih edin. İstemci Bileşeni içerisine eklenen Promise’ler her oluşturma işlemi sırasında yeniden oluşturulur. Sunucu Bileşeninden İstemci Bileşenine aktarılan Promise’ler ise yeniden oluşturma işlemleri sırasında sabit kalır. Bu örneği inceleyin.

Kullanım

use ile context okumak

use’a context aktarıldığında, useContext gibi çalışacaktır. useContext bileşende üst seviye olarak çağırılmak zorundayken; use ifadesi, if gibi koşullu ifadelerin ve for gibi döngü ifadelerinin içerisinde kullanılabilir. Çok daha esnek kullanılabildiğinden dolayı use ifadesi, useContext yerine tercih edilebilir.

import { use } from 'react';

function Button() {
const theme = use(ThemeContext);
// ...

use, içerisine aktarmış olduğunuz context’in context değerini döndürür. Context değerini belirlemek için React, bileşen ağacını arar ve ilgili context için en yakın context sağlayıcısını bulur.

Bir Button’a context aktarmak için, onu veya üst bileşenlerinden herhangi birini Context sağlayıcısının içerisine ekleyin.

function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}

function Form() {
// ... içerideki button'ları yeniden oluşturur ...
}

Sağlayıcı ile Button arasında kaç katman olduğu önemli değildir. Form içerisinde herhangi bir yerdeki Button, use(ThemeContext)’i çağırdığında değer olarak "dark" alacaktır.

useContext aksine; use, döngüler ve if gibi koşullu ifadeler içerisinde kullanılabilir.

function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}

use, bir if ifadesinin içerisinde çağırılır. Bu size Context verilerini koşullu olarak okuma imkanı verir.

Tuzak

use(context), useContext gibi her zaman çağırıldığı bileşenin üstündeki en yakın context sağlayıcısını arar. Yukarı doğru arama yapar ve use(context)’i çağırdığınız bileşendeki context sağlayıcılarını dikkate almaz.

import { createContext, use } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

function Form() {
  return (
    <Panel title="Hoşgeldin">
      <Button show={true}>Kayıt ol</Button>
      <Button show={false}>Giriş Yap</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = use(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ show, children }) {
  if (show) {
    const theme = use(ThemeContext);
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {children}
      </button>
    );
  }
  return false
}

Sunucudan istemciye veri aktarımı

Sunucudan gelen veri; Sunucu Bileşeni’nden İstemci Bileşeni’ne Promise biçiminde prop olarak aktarılır.

import { fetchMessage } from './lib.js';
import { Message } from './message.js';

export default function App() {
const messagePromise = fetchMessage();
return (
<Suspense fallback={<p>Mesaj bekleniyor...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

İstemci Bileşeni prop olarak iletilen Promise’i alır ve use API’ına ileterek kullanır. Bu yöntem Sunucu Bileşeni içerisinde oluşturulan Promise’ten alınan verinin İstemci Bileşeni tarafından okunmasına olanak tanır.

// message.js
'use client';

import { use } from 'react';

export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Aktarılan Mesaj: {messageContent}</p>;
}

Message bir Suspense içerisinde olduğu için Promise çözümleninceye kadar yedek görünüm görüntülenecektir. Promise çözümlendiğinde değer use API tarafından okunacak ve Message bileşeni Suspense’in yedek görünüm ile yer değiştirecektir.

"use client";

import { use, Suspense } from "react";

function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Aktarılan Mesaj: {messageContent}</p>;
}

export function MessageContainer({ messagePromise }) {
  return (
    <Suspense fallback={<p>⌛Mesaj Yükleniyor...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  );
}

Not

Sunucu Bileşeni’nden İstemci Bileşeni’ne Promise aktarıldığında çözümlenen değer sunucu ile istemci arasından geçmesi için serileştirilebilir olması gerekir. Fonksiyonlar gibi veri türleri serileştirilemezler ve Promise’in çözümlenen değeri olamazlar.

Derinlemesine İnceleme

Promise’i Sunucu Bileşeninde mi yoksa İstemci Bileşeninde mi çözümlemeliyim?

Promise, Sunucu Bileşeni’nden İstemci Bileşeni’ne aktarılabilir ve İstemci Bileşeni içerisinde use API kullanarak çözümlenebilir. Yanı sıra istersen Promise’i Sunucu Bileşeni içerisinde await kullanarak çözümleyebilir ve gerekli veriyi İstemci Bileşeni içerisine prop olarak iletebilirsin.

export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}

Ancak Sunucu Bileşeni içerisinde await kullanımı, await ifadesi tamamlanana kadar oluşturma işlemini engeller. Sunucu Bileşeni’nden İstemci Bileşeni’ne Promise geçirmek Sunucu Bileşeni içerisinde Promise kaynaklı olan oluşturma işleminin engellenmesini önler.

Reddedilen Promise’ler ile başa çıkmak

Bazen use’a aktarılan Promise reddedilebilir. Reddedilen Promise’leri şu şekilde yönetebilirsiniz:

  1. Kullanıcıya hata sınırlayıcısı kullanarak hata göstermek.
  2. Promise.catch methodunu kullanarak alternatif bir veri sunmak

Tuzak

use, try-catch bloğu içerisinde çağırılamaz. Try-catch bloğu yerine bileşeni Error Boundary içerisine ekleyin, ya da Promise’in .catch methodundan yararlanarak alternatif bir değer sağlayın.

Kullanıcıya hata sınırlayıcısı kullanarak hata göstermek

Eğer bir Promise reddedildiğinde kullanıcılarına hata göstermek istersen hata sınırlayıcısını kullanabilirsin. Bir hata sınırlayıcı kullanmak için use API’ını çağırdığınız bir bileşeni Error Boundary içerisine koyun. Eğer use’a iletilen Promise reddedilirse hata sınırlayıcı aracılığı ile yedek görünüm görüntülenecektir.

"use client";

import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>⚠️Bir şeyler yanlış gitti</p>}>
      <Suspense fallback={<p>⌛Mesaj indiriliyor...</p>}>
        <Message messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Message({ messagePromise }) {
  const content = use(messagePromise);
  return <p>Aktarılan mesaj: {content}</p>;
}

Promise.catch methodunu kullanarak alternatif bir veri sunmak

Eğer use’a aktarılan Promise reddedildiğinde yerine alternatif bir değer sağlamak istiyorsan Promise’in catch methodunu kullanabilirsin.

import { Message } from './message.js';

export default function App() {
const messagePromise = new Promise((resolve, reject) => {
reject();
}).catch(() => {
return "yeni mesaj bulunamadı.";
});

return (
<Suspense fallback={<p>Mesaj bekleniyor...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

Promise’in catch methodunu kullanmak için Promise objesinden catch’i çağır. catch tek bir argüman alır: Bir hata mesajını argüman olarak alan bir fonksiyon. catch’e geçirilen fonskiyon tarafından döndürülen her şey, Promise’in çözümlenen değeri olarak kullanılacaktır.


Sorun Giderme

“Suspense İstisnası: Bu gerçek bir hata değil!”

use ya bir React Bileşeni ya da Hook fonksiyonu dışında veya try-catch bloğu içerisinde çağırılıyor. Eğer try-catch bloğu içerisinde use çağırıyorsanız bileşeni hata sınırlandırıcı içerisine koyun veya hata yakalamak ve alternatif değer ile çözümlemek için Promise’in catch methodunu çağırın. Bu örneği inceleyin

Eğer use’u bir React Bileşeni veya Hook fonksiyonu dışında çağırıyorsanız use çağrısını bir React Bileşeni veya Hook fonksiyonu içerisine taşıyın.

function MessageComponent({messagePromise}) {
function download() {
// ❌ `use`, bir Bileşen veya Hook olmayan fonksiyon tarafından çağırılıyor
const message = use(messagePromise);
// ...

Bunun yerine, use fonksiyonunu herhangi bir bileşen kapanışının dışında çağırın. use fonksiyonunu çağıran fonksiyon bir bileşen veya Hook olmalıdır.

function MessageComponent({messagePromise}) {
// ✅ `use` bir bileşen içerisine çağırılıyor.
const message = use(messagePromise);
// ...