useContext, bileşeninizden context’e abone olmanıza ve değerini okumanıza izin veren React Hook’udur.

const value = useContext(SomeContext)

Referans

useContext(SomeContext)

context’e abone olmak ve değerini okumak için useContext’i bileşeninizin üst düzeyinde çağırın.

import { useContext } from 'react';

function MyComponent() {
const theme = useContext(ThemeContext);
// ...

Daha fazla örnek için aşağıya bakın.

Parametreler

  • SomeContext: Daha önce createContext ile oluşturduğunuz context. Context’in kendisi bilgileri tutmaz, yalnızca tedarik edeceğiniz ya da bileşenlerden okuyacağınız bilginin türünü temsil eder.

Dönüş değerleri

useContext, çağrılan bileşen için Context değerini döndürür. Bu değer, ağaçtaki çağrılan bileşenden önceki en yakın SomeContext.Provider’a iletilen value olarak belirlenir. Böyle bir sağlayıcı yoksa, döndürülen değer o Context için createContext ile belirlediğiniz defaultValue olacaktır. Döndürülen değer her zaman günceldir. Eğer bir Context değişirse, React otomatik olarak bu Context’i kullanan bileşenleri yeniden render eder.

Dikkat Edilmesi Gerekenler

  • Bir bileşende yapılan useContext() çağrısı, aynı bileşenden döndürülen sağlayıcılardan etkilenmez. İlgili <Context.Provider> kullanılan bileşenin üstünde olmalıdır.
  • React, farklı bir value alan sağlayıcıdan başlayarak, belirli bir Context’i kullanan tüm alt bileşenleri otomatik olarak yeniden render eder. Önceki ve sonraki değerler Object.is karşılaştırması ile karşılaştırılır. memo ile yeniden renderları atlamak, alt bileşenlerin taze Context değerleri almasını engellemez.
  • Yapı sistemimiz çıktıda modüllerin kopyalarını oluşturursa (sembolik bağlantılarla olabilir), bu Context’i bozabilir. Bir şeyi Context aracılığıyla geçirmek, Context sağlamak ve okumak için tamamen aynı nesne olan SomeContext’ın, === karşılaştırması ile belirlendiği durumlarda çalışır.

Kullanım

Veri geçişini ağaca derinlemesine sağlama

Bileşeninizin üst düzeyinde useContext’i çağırarak context’e abone olabilir ve değerini okuyabilirsiniz:

import { useContext } from 'react';

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

useContext, parametre olarak geçtiğiniz context için context değerini döndürür. Context değerini belirlemek için, React bileşen ağacını tarar ve context’e özgü en yakındaki context sağlayıcısını bulur.

Button bileşenine context geçmek için, bileşeni veya üst bileşenlerinden birini ilgili context sağlayıcısına sarın:

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

function Form() {
// ... renders buttons inside ...
}

Button ile sağlayıcı arasında ne kadar katman olduğu önemsizdir. Form’un herhangi bir yerindeki Button’da useContext(ThemeContext) çağırıldığında "dark" değerini alacaktır.

Tuzak

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

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

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

function Form() {
  return (
    <Panel title="Welcome">
      <Button>Sign up</Button>
      <Button>Log in</Button>
    </Panel>
  );
}

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

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}


Context üzerinden geçirilen verileri güncelleme

Genellikle, context’in zaman içinde değişmesini istersiniz. Context’i güncellemek için, state ile birlikte kullanın. Üst bileşende bir state değişkeni tanımlayın ve state’i sağlayıcının context değeri olarak aşağıya geçirin.

function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext.Provider>
);
}

Artık sağlayıcı içerisindeki herhangi bir Button, güncel theme değerini alacaktır. setThemei çağırarak sağlayıcıya iletilen theme değerini güncellerseniz, tüm Button bileşenleri yeni 'light' değeriyle yeniden render olacaktır.

Context güncelleme örnekleri

Örnek 1 / 5:
Context aracılığıyla bir değerin güncellenmesi

Bu örnekte, MyApp bileşeni, daha sonra ThemeContext sağlayıcısına iletilecek olan bir state değişkenine sahiptir. “Karanlık mod” onay kutusunu işaretlemek, state’i günceller. Sağlanan değerin değiştirilmesi, o context’i kullanan tüm bileşenlerin yeniden render edilmesine neden olur.

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext.Provider value={theme}>
      <Form />
      <label>
        <input
          type="checkbox"
          checked={theme === 'dark'}
          onChange={(e) => {
            setTheme(e.target.checked ? 'dark' : 'light')
          }}
        />
        Use dark mode
      </label>
    </ThemeContext.Provider>
  )
}

function Form({ children }) {
  return (
    <Panel title="Welcome">
      <Button>Sign up</Button>
      <Button>Log in</Button>
    </Panel>
  );
}

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

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}

value="dark" ifadesinin "dark" dizisini ilettiğini, value={theme} ifadesinin JavaScript theme değişkeninin değerini JSX süslü parantezi ile ilettiğini unutmayın. Süslü parantezler aynı zamanda dizi olmayan değerleri iletmenize olanak tanır.


Varsayılan fallback değeri belirtme

React, üst ağaçta söz konusu context’in sağlayıcısını bulamazsa, useContext() tarafından döndürülen değer context’i oluştururken belirttiğiniz varsayılan değer olacaktır:

const ThemeContext = createContext(null);

Varsayılan değer asla değişmez. Eğer context’i güncelleyebilmek istiyorsanız, yukarıda açıklandığı gibi state ile birlikte kullanın.

Genellikle varsayılan değer olarak null yerine kullanabileceğiniz daha anlamlı bir değer vardır, örneğin:

const ThemeContext = createContext('light');

Bu sayede, kazara sağlayıcı tanımlamadan bazı bileşenleri render ederseniz, kod kırılmaz. Ayrıca, bileşenlerinizin bir sürü sağlayıcı ayarlanmadan test ortamında iyi çalışmasını sağlar.

Aşağıdaki örnekte, “Temayı değiştir” butonu her zaman açık renkli olarak görüntülenir çünkü tema context’i sağlayıcısının dışında yer alır ve varsayılan context değeri 'açık'tır. Varsayılan temayı 'koyu' olarak düzenlemeyi deneyin.

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext('light');

export default function MyApp() {
  const [theme, setTheme] = useState('light');
  return (
    <>
      <ThemeContext.Provider value={theme}>
        <Form />
      </ThemeContext.Provider>
      <Button onClick={() => {
        setTheme(theme === 'dark' ? 'light' : 'dark');
      }}>
        Toggle theme
      </Button>
    </>
  )
}

function Form({ children }) {
  return (
    <Panel title="Welcome">
      <Button>Sign up</Button>
      <Button>Log in</Button>
    </Panel>
  );
}

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

function Button({ children, onClick }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className} onClick={onClick}>
      {children}
    </button>
  );
}


Ağacın bir kısmında context’i geçersiz kılma

Ağacın bir bölümünü farklı bir değere sahip sağlayıcıyla sarmalayarak context’i geçersiz kılabilirsiniz.

<ThemeContext.Provider value="dark">
...
<ThemeContext.Provider value="light">
<Footer />
</ThemeContext.Provider>
...
</ThemeContext.Provider>

İhtiyacınız olduğu kadar çok sağlayıcıyı iç içe yerleştirebilir ve geçersiz kılabilirsiniz.

Context'i geçersiz kılınma örnekleri

Örnek 1 / 2:
Temanın geçersiz kılınması

Burada Footer içerisindeki buton, dışındaki butonlardan ("dark") farklı bir context değeri ("light") alır.

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

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

function Form() {
  return (
    <Panel title="Welcome">
      <Button>Sign up</Button>
      <Button>Log in</Button>
      <ThemeContext.Provider value="light">
        <Footer />
      </ThemeContext.Provider>
    </Panel>
  );
}

function Footer() {
  return (
    <footer>
      <Button>Settings</Button>
    </footer>
  );
}

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

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}


Nesneler ve fonksiyonları geçirirken tekrar render işlemlerini optimize etmek

Herhangi bir değeri, nesne veya fonksiyon dahil, context aracılığıyla iletebilirsiniz.

function MyApp() {
const [currentUser, setCurrentUser] = useState(null);

function login(response) {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}

return (
<AuthContext.Provider value={{ currentUser, login }}>
<Page />
</AuthContext.Provider>
);
}

Burada, context değeri iki özellikli JavaScript nesnesidir ve bunlardan biri fonksiyondur. MyApp yeniden render edildiğinde (örneğin, bir rota güncellendiğinde), farklı fonksiyona işaret eden farklı bir nesne olur. Bu nedenle React, ağaçtaki useContext(AuthContext) çağrılan tüm bileşenlerin yeniden render etmek zorunda kalır.

Daha küçük uygulamalarda bu bir sorun değildir. Ancak, currentUser gibi altında yatan veriler değişmediyse, bunları yeniden render etmek gerekli değildir. React’ın bu gerçeği kullanmasına yardımcı olmak için, login fonksiyonunu useCallback ve nesne oluşturmayı useMemo ile sarmalayabilirsiniz. Bu bir performans optimizasyonudur:

import { useCallback, useMemo } from 'react';

function MyApp() {
const [currentUser, setCurrentUser] = useState(null);

const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);

const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);

return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}

Bu değişiklik sonucunda, MyApp yeniden render edilse bile, useContext(AuthContext) çağıran bileşenler, currentUser değişmediği sürece yeniden render edilmeyecektir.

useMemo ve useCallback hakkında daha fazla bilgi edinin.


Sorun giderme

Bileşenim sağlayıcının değerini görmüyor

Bunun birkaç yaygın sebebi vardır:

  1. useContext()’i çağırdığınız bileşenle aynı bileşende <SomeContext.Provider> render ediyorsunuz. <SomeContext.Provider>’ı useContext() çağıran bileşenin üstüne ve dışına taşıyın.
  2. Bileşeninizi SomeContext.Provider ile sarmalamayı unutmuş ya da ağacın istem dışı bir yerine yerleştirmiş olabilirsiniz. React DevTools kullanarak hiyerarşinin doğru olup olmadığını kontrol edin.
  3. Kullandığınız araçlardan kaynaklı, sağlayan bileşen tarafından görülen SomeContext ile okuyan bileşen tarafından görülen SomeContext nesnesinin iki farklı nesne olmasına neden olan derleme sorunlarıyla karşılaşabilirsiniz. Örneğin, sembolik bağlantılar kullanıyorsanız bu yaşanabilir. Bu durumu, window.SomeContext1 ve window.SomeContext2 gibi global değişkenlere atayıp konsolda window.SomeContext1 === window.SomeContext2 kontrolü yaparak doğrulayabilirsiniz. Eğer aynı değillerse, derleme aracı seviyesinde sorunu düzeltin.

Varsayılan değer farklı olsa bile context’den her zaman undefined alıyorum

Ağaçta value verilmemiş bir sağlayıcı olabilir:

const MyContext = React.createContext('default');

function MyComponent() {
const value = useContext(MyContext);
// ...
}

value belirtmeyi unutursanız, value={undefined} geçmiş gibi davranır .

Yanlışlıkla farklı bir özellik adı kullanmış da olabilirsiniz:

// 🚩 Çalışmaz: özellik "value" olarak adlandırılmalı
<ThemeContext.Provider theme={theme}>
<Button />
</ThemeContext.Provider>

Her iki durumda da konsolda React uyarısı görmelisiniz. Bunları düzeltmek için prop’u value olarak adlandırın:

// ✅ value prop'unu geçirme
<ThemeContext.Provider value={theme}>
<Button />
</ThemeContext.Provider>

Unutmayın, createContext(defaultValue) çağrınızdaki varsayılan değer yalnızca eşleşen hiçbir sağlayıcı yoksa kullanılır. Alt ağaçta bir yerde <SomeContext.Provider value={undefined}> bileşeni varsa, useContext(SomeContext) çağrısını yapan bileşen context değeri olarak undefined alacaktır.