use

use, bir Promise veya context değerini okumanızı sağlayan bir React API’sidir.

const value = use(resource);

Referans

use(context)

Değerini okumak için use’u bir context ile çağırın. useContext’in aksine, use loop’lar ve if gibi conditional statement’lar içinde çağrılabilir.

import { use } from 'react';

function Button() {
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.

Daha fazla örneği aşağıda görün.

Parametreler

Döndürür

Geçirilen context için context value’yu döndürür; bu değer, çağrıyı yapan component’in üstündeki en yakın context provider tarafından belirlenir. Eğer provider yoksa, döndürülen değer createContext’e geçirilen defaultValue olur.

Uyarılar

  • use, bir Component veya Hook içinde çağrılmalıdır.
  • use ile context okumak Server Components içinde desteklenmez.

use(promise)

Resolved value’sunu okumak için use’u bir Promise ile çağırın. use çağıran component, Promise pending durumdayken suspend olur. İsminin aksine, use bir Hook değildir. Hook’ların aksine, loop’lar ve if gibi conditional statement’lar içinde çağrılabilir.

import { use } from 'react';

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

If the component that calls use is wrapped in a Suspense boundary, the fallback will be displayed while the Promise is pending. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by use. If the Promise is rejected, the fallback of the nearest Error Boundary will be displayed.

See more examples below.

Parameters

  • promise: A Promise whose resolved value you want to read. The Promise must be cached so that the same instance is reused across re-renders.

Returns

The resolved value of the Promise.

Caveats

  • use must be called inside a Component or a Hook.
  • use cannot be called inside a try-catch block. Instead, wrap your component in an Error Boundary to catch the error and display a fallback.
  • Promises passed to use must be cached so the same Promise instance is reused across re-renders. See caching Promises below.
  • When passing a Promise from a Server Component to a Client Component, its resolved value must be serializable.

Usage (Context)

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.

Bir context, use’a geçirildiğinde useContext ile benzer şekilde çalışır. useContext component’inizin top-level’ında çağrılmak zorundayken, use if gibi conditional’lar ve for gibi loop’lar içinde çağrılabilir.

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 value="dark">
<Form />
</ThemeContext>
);
}

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 value="dark">
      <Form />
    </ThemeContext>
  )
}

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
}

Context’ten Promise okuma

Prop drilling olmadan asynchronous data paylaşmak için, bir Promise’i context value olarak ayarlayın, ardından use(context) ile okuyun ve use(promise) ile resolve edin:

import { use } from 'react';
import { UserContext } from './UserContext';

function Profile() {
const userPromise = use(UserContext);
const user = use(userPromise);
return <h1>{user.name}</h1>;
}

Reading the value requires two use calls because the context value itself isn’t awaited. See Before you use context for alternatives to consider before reaching for context.

Wrap the components that read the Promise in a Suspense boundary so only that subtree suspends while the Promise is pending. See Usage (Promises) below for more on reading Promises with use.

Tuzak

When this pattern is used with Server Components, refetching the Promise requires refetching the Server Component that sets the Promise in context. Avoid setting the Promise in context high in the tree, since that would refetch large parts of the app unnecessarily.


Usage (Promises)

Reading a Promise with use

Call use with a Promise to read its resolved value. The component will suspend while the Promise is pending.

import { use } from 'react';

function Albums({ albumsPromise }) {
const albums = use(albumsPromise);
return (
<ul>
{albums.map(album => (
<li key={album.id}>
{album.title} ({album.year})
</li>
))}
</ul>
);
}

Wrap the component that calls use in a Suspense boundary so React can show a fallback while the Promise is pending. The closest Suspense boundary above the suspending component shows its fallback. Once the Promise resolves, React reads the value with use and replaces the fallback with the rendered component.

Reading a Promise with use vs fetching in an Effect

Örnek 1 / 2:
Fetching data with use

In this example, Albums calls use with a cached Promise. The component suspends while the Promise is pending, and React displays the nearest Suspense fallback. Rejected Promises propagate to the nearest Error Boundary.

import { use, Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { fetchData } from './data.js';

export default function App() {
  return (
    <ErrorBoundary fallback={<p>Could not fetch albums.</p>}>
      <Suspense fallback={<Loading />}>
        <Albums />
      </Suspense>
    </ErrorBoundary>
  );
}

function Albums() {
  const albums = use(fetchData('/albums'));
  return (
    <ul>
      {albums.map(album => (
        <li key={album.id}>
          {album.title} ({album.year})
        </li>
      ))}
    </ul>
  );
}

function Loading() {
  return <h2>Loading...</h2>;
}

Tuzak

Promises passed to use must be cached

Promises created during render are recreated on every render, which causes React to show the Suspense fallback repeatedly and prevents content from appearing.

function Albums() {
// 🔴 `fetch` creates a new Promise on every render.
const albums = use(fetch('/albums'));
// ...
}

Instead, pass a Promise from a cache, a Suspense-enabled framework, or a Server Component:

// ✅ fetchData reads the Promise from a cache.
const albums = use(fetchData('/albums'));
Derinlemesine İnceleme

Why are Promises recreated on every render?

React doesn’t preserve state for renders that suspended before mounting. After each suspension, React retries rendering from scratch, so any Promise created during render is recreated.

Common ways a Promise can be unintentionally recreated during render:

function Albums() {
// 🔴 `fetch` creates a new Promise on every render.
const albums = use(fetch('/albums'));

// 🔴 Uncached `async` function calls create a new Promise on every render.
const albums = use((async () => {
const res = await fetch('/albums');
return res.json();
})());

// 🔴 Adding `.then` returns a new Promise on every render,
// even if `fetchData` is cached.
const albums = use(fetchData('/albums').then(res => res.json()));
// ...
}

Ideally, Promises are created before rendering, such as in an event handler, a route loader, or a Server Component, and passed to the component that calls use. Fetching lazily in render delays network requests and can create waterfalls.

// ✅ fetchData reads the Promise from a cache.
const albums = use(fetchData('/albums'));

Caching Promises for Client Components

Promises passed to use in Client Components must be cached so the same Promise instance is reused across re-renders. If a new Promise is created directly in render, React will display the Suspense fallback on every re-render.

// ✅ Cache the Promise so the same one is reused across renders
let cache = new Map();

export function fetchData(url) {
if (!cache.has(url)) {
cache.set(url, getData(url));
}
return cache.get(url);
}

The fetchData function returns the same Promise each time it’s called with the same URL. When use receives the same Promise on a re-render, it reads the already-resolved value synchronously without suspending.

Not

The way you cache Promises depends on the framework you use with Suspense. Frameworks typically provide built-in caching mechanisms. If you don’t use a framework, you can use a simple module-level cache like the one above, or a Suspense-enabled data source.

In the example below, clicking “Re-render” updates state in App and triggers a re-render. Because fetchData returns the same cached Promise, Albums reads the value synchronously instead of showing the Suspense fallback again.

import { use, Suspense, useState } from 'react';
import { fetchData } from './data.js';

export default function App() {
  const [count, setCount] = useState(0);
  return (
    <>
      <button onClick={() => setCount(count + 1)}>
        Re-render
      </button>
      <p>Render count: {count}</p>
      <Suspense fallback={<p>Loading...</p>}>
        <Albums />
      </Suspense>
    </>
  );
}

function Albums() {
  const albums = use(fetchData('/albums'));
  return (
    <ul>
      {albums.map(album => (
        <li key={album.id}>
          {album.title} ({album.year})
        </li>
      ))}
    </ul>
  );
}

Derinlemesine İnceleme

How to implement a promise cache

A basic cache stores the Promise keyed by URL so the same instance is reused across renders. To also avoid unnecessary Suspense fallbacks when data is already available, you can set status and value (or reason) fields on the Promise. React checks these fields when use is called: if status is 'fulfilled', it reads value synchronously without suspending. If status is 'rejected', it throws reason. If the field is missing or 'pending', it suspends.

let cache = new Map();

function fetchData(url) {
if (!cache.has(url)) {
const promise = getData(url);
promise.status = 'pending';
promise.then(
value => {
promise.status = 'fulfilled';
promise.value = value;
},
reason => {
promise.status = 'rejected';
promise.reason = reason;
},
);
cache.set(url, promise);
}
return cache.get(url);
}

This is primarily useful for library authors building Suspense-compatible data layers. React will set the status field itself on Promises that don’t have it, but setting it yourself avoids an extra render when the data is already available.

This cache pattern is the foundation for re-fetching data (where changing the cache key triggers a new fetch) and preloading data on hover (where calling fetchData early means the Promise may already be resolved by the time use reads it).

Tuzak

Don’t skip calling use based on whether a Promise is already settled.

Unlike other hooks, use can be called inside conditions and loops — but it must always be called for the Promise itself. Never read promise.status or promise.value directly to bypass use; always pass the Promise to use and let React handle it.

// 🔴 Don't bypass `use` by reading promise status directly
if (promise.status === 'fulfilled') {
return promise.value;
}
const value = use(promise);
// ✅ Pass the promise to `use` and let React track the promise
const value = use(promise);

Bypassing use this way can break React Suspense optimizations and Suspense features for React DevTools. You can use(promise) conditionally, but don’t conditionally use(promise) based on the promise itself.


Re-fetching data in Client Components

To refresh data at the same URL (for example, with a “Refresh” button), invalidate the cache entry and start a new fetch inside a startTransition. Store the resulting Promise in state to trigger a re-render. While the new Promise is pending, React keeps showing the existing content because the update is inside a Transition.

function App() {
const [albumsPromise, setAlbumsPromise] = useState(fetchData('/albums'));
const [isPending, startTransition] = useTransition();

function handleRefresh() {
startTransition(() => {
setAlbumsPromise(refetchData('/albums'));
});
}
// ...
}

refetchData clears the old cache entry and starts a new fetch at the same URL. Storing the resulting Promise in state triggers a re-render inside the Transition. On re-render, Albums receives the new Promise and use suspends on it while React keeps showing the old content.

import { Suspense, useState, useTransition } from 'react';
import { use } from 'react';
import { fetchData, refetchData } from './data.js';

export default function App() {
  const [albumsPromise, setAlbumsPromise] = useState(
    () => fetchData('/the-beatles/albums')
  );
  const [isPending, startTransition] = useTransition();

  function handleRefresh() {
    startTransition(() => {
      setAlbumsPromise(refetchData('/the-beatles/albums'));
    });
  }

  return (
    <>
      <button
        onClick={handleRefresh}
        disabled={isPending}
      >
        {isPending ? 'Refreshing...' : 'Refresh'}
      </button>
      <div style={{ opacity: isPending ? 0.6 : 1 }}>
        <Suspense fallback={<Loading />}>
          <Albums albumsPromise={albumsPromise} />
        </Suspense>
      </div>
    </>
  );
}

function Albums({ albumsPromise }) {
  const albums = use(albumsPromise);
  return (
    <ul>
      {albums.map(album => (
        <li key={album.id}>
          {album.title} ({album.year})
        </li>
      ))}
    </ul>
  );
}

function Loading() {
  return <h2>Loading...</h2>;
}

Not

Frameworks that support Suspense typically provide their own caching and invalidation mechanisms. The custom cache above is useful for understanding the pattern, but in practice prefer your framework’s data fetching solution.


Preloading data on hover

You can start loading data before it’s needed by calling fetchData during a hover event. Since fetchData caches the Promise, the data may already be available by the time the user clicks. If the Promise has resolved by the time use reads it, React renders the component immediately without showing a Suspense fallback.

<button
onMouseEnter={() => fetchData(`/${id}/albums`)}
onClick={() => {
startTransition(() => {
setArtistId(id);
});
}}
>

In this example, hovering over an artist button starts fetching their albums in the background. Without hovering first, clicking shows a loading fallback. Try hovering over a button for a moment before clicking to see the difference.

import { Suspense, useState, useTransition } from 'react';
import Albums from './Albums.js';
import { fetchData } from './data.js';

export default function App() {
  const [artistId, setArtistId] = useState('the-beatles');
  const [isPending, startTransition] = useTransition();

  return (
    <>
      <div>
        {['the-beatles', 'led-zeppelin', 'pink-floyd'].map(id => (
          <button
            key={id}
            onMouseEnter={() => {
              fetchData(`/${id}/albums`);
            }}
            onClick={() => {
              startTransition(() => {
                setArtistId(id);
              });
            }}
          >
            {id === 'the-beatles' ? 'The Beatles' :
             id === 'led-zeppelin' ? 'Led Zeppelin' :
             'Pink Floyd'}
          </button>
        ))}
      </div>
      <Suspense key={artistId} fallback={<Loading />}>
        <Albums artistId={artistId} />
      </Suspense>
    </>
  );
}

function Loading() {
  return <h2>Loading...</h2>;
}


Streaming data from server to client

Data can be streamed from the server to the client by passing a Promise as a prop from a Server Component to a Client Component.

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>
);
}

Client Component daha sonra prop olarak aldığı Promise’i alır ve use API’sine geçirir. Bu, Client Component’in başlangıçta Server Component tarafından oluşturulan Promise’ten gelen değeri okumasını sağlar.

// 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 boundary’si ile sarıldığı için, Promise resolve edilene kadar fallback gösterilir. Promise resolve edildiğinde, değer use API’si tarafından okunur ve Message component’i Suspense fallback’inin yerini alır.

"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>
  );
}

Derinlemesine İnceleme

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

Bir Promise, bir Server Component içinde await ile resolve edilebilir veya bir Client Component’e prop olarak geçirilip orada use ile resolve edilebilir.

Bir Server Component içinde await kullanmak Server Component’in kendisini suspend eder ve Client Component resolved value’yu prop olarak alır:

// Server Component
export default async function App() {
// Server Component’i suspend eder.
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />;
}

Bir Server Component ayrıca bir Promise’i await etmeden başlatabilir ve Promise’i bir Client Component’e geçirebilir. Server Component hemen return eder ve Client Component use çağırdığında suspend olur:

// Server Component
export default function App() {
// Await edilmedi: burada başlar, client’ta resolve olur.
const messagePromise = fetchMessage();
return <Message messagePromise={messagePromise} />;
}
// Client Component
'use client';
import { use } from 'react';

export function Message({ messagePromise }) {
// Data available olana kadar suspend eder.
const messageContent = use(messagePromise);
return <p>{messageContent}</p>;
}

Mümkün olduğunda Server Component içinde await kullanmayı tercih edin; çünkü bu, data fetching’i server tarafında tutar. Eğer üstteki bir Server Component data’yı zaten await ediyorsa, use çağırmak için yeni bir Promise oluşturmak yerine resolved value’yu prop olarak aşağı geçirin.

Ayrıca promise’i await etmeden bir Client Component’e prop olarak geçirebilir ve ardından tree’nin daha derininde suspend etmek için use(promise) ile okuyabilirsiniz. Bu, Promise pending durumdayken çevredeki UI’ın daha büyük bir kısmının tamamlanmasına olanak tanır. Yaygın bir durum, popover ve tooltip gibi interactive content’lerdir; burada data yalnızca hover veya click sonrasında gerekir. Client Component’ler await kullanamaz, bu yüzden bir Promise üzerinde suspend olmak için use’a güvenirler.

Her iki durumda da, Promise’i okuyan component’i bir Suspense boundary ile sarın; böylece React, Promise pending durumdayken bir fallback gösterebilir. Boundary placement konusunda rehberlik için Revealing content together at once bölümüne bakın.


Error Boundary ile hata gösterme

use’a geçirilen Promise rejected olursa, error en yakın Error Boundary’ye propagate edilir. Promise rejected olduğunda bir fallback göstermek için use çağıran component’i bir Error Boundary ile sarın.

Aşağıdaki örnekte, fetchData ilk denemede reject olur ve retry sırasında başarılı olur. Error Boundary rejection’ı yakalar ve “Try again” button’u olan bir fallback gösterir.

import { use, Suspense, useState, startTransition } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { fetchData, refetchData } from "./data.js";

export default function App() {
  const [albumsPromise, setAlbumsPromise] = useState(
    () => fetchData('/the-beatles/albums')
  );

  function handleRetry() {
    startTransition(() => {
      setAlbumsPromise(refetchData('/the-beatles/albums'));
    });
  }

  return (
    <ErrorBoundary
      resetKeys={[albumsPromise]}
      fallbackRender={() => (
        <>
          <p>⚠️ Albümler yüklenirken bir sorun oluştu.</p>
          <button onClick={handleRetry}>Tekrar deneyin</button>
        </>
      )}
    >
      <Suspense fallback={<p>Yükleniyor...</p>}>
        <Albums albumsPromise={albumsPromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Albums({ albumsPromise }) {
  const albums = use(albumsPromise);
  return (
    <ul>
      {albums.map(album => (
        <li key={album.id}>
          {album.title} ({album.year})
        </li>
      ))}
    </ul>
  );
}


Sorun Giderme

Şu hatayı alıyorum: “Suspense Exception: This is not a real error!”

use’u bir try-catch block’u içinde çağırıyorsunuz. use, Suspense ile entegre olmak için internal olarak throw eder, bu yüzden try-catch ile sarılamaz. Bunun yerine, error’ları handle etmek için use çağıran component’i bir Error Boundary ile sarın.

function Albums({ albumsPromise }) {
try {
// ❌ Don't wrap `use` in try-catch
const albums = use(albumsPromise);
} catch (e) {
return <p>Error</p>;
}
// ...

Bunun yerine, component’i bir Error Boundary ile sarın:

function Albums({ albumsPromise }) {
// ✅ Call `use` without try-catch
const albums = use(albumsPromise);
// ...
// ✅ Use an Error Boundary to handle errors
<ErrorBoundary fallback={<p>Error</p>}>
<Albums albumsPromise={albumsPromise} />
</ErrorBoundary>

Şu uyarıyı alıyorum: “A component was suspended by an uncached promise”

use’a geçirilen Promise cache’lenmemiştir, bu yüzden React onu re-render’lar arasında yeniden kullanamaz.

Bu durum genellikle render sırasında doğrudan fetch veya bir async function çağrıldığında olur:

function Albums() {
// 🔴 This creates a new Promise on every render
const albums = use(fetch('/albums'));
// ...
}

Bunu düzeltmek için, aynı instance’ın yeniden kullanılmasını sağlayacak şekilde Promise’i cache’leyin:

// ✅ fetchData returns the same Promise for the same URL
const albums = use(fetchData('/albums'));

Daha fazla detay için Client Components için Promise cache’leme bölümüne bakın.