useContext, bileşeninizden context okumanıza ve buna abone olmanıza izin veren bir React Hook’tur.

const value = useContext(SomeContext)

Referans

useContext(SomeContext)

Bileşeninizde context okumak ve buna abone olmak için useContext‘i bileşeninizin üst düzeyinde çağırın.

import { useContext } from 'react';

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

Aşağıda daha fazla örneğe bakın.

Parametreler

  • SomeContext: Daha önce createContext ile oluşturduğunuz context. Context kendisi bilgiyi tutmaz, sadece bileşenlere sağlayabileceğiniz veya okuyabileceğiniz bilgi türünü temsil eder.

Dönüşler

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‘a erişebilir ve abone olabilirsiniz:

import { useContext } from 'react';

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

useContext, 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 o belirli context için en yakın Context sağlayıcısını bulur.

Button bileşenine Context geçmek için, ilgili Context sağlayıcısını bu bileşenin veya üst bileşeninin içine yerleştirin:

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

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

Button‘ın içinde olduğu herhangi bir yerde useContext(ThemeContext) çağrıldığında, Form‘un içindeki ThemeContext.Provider bileşenine en yakın olanın "dark" değeri alınır.

Tuzak

useContext(), onu çağıran bileşenden yukarı doğru arama yapar ve arama sırasında 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 birleştirin. Ana bileşende bir durum değişkeni bildirin ve geçerli durumu 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>
);
}

Şimdi sağlayıcı içindeki herhangi bir Button, mevcut 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 bir durum değişkenini tutar ve daha sonra ThemeContext sağlayıcısına iletilir. “Karanlık mod” onay kutusunu işaretlemek, durumu günceller. Sağlanan değerin değiştirilmesi, bu 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" ifadesi "dark" string değerini geçerken, value={theme} ifadesi JavaScript theme değişkeninin değerini JSX curly braces ({}) ile geçirir. Curly braces ayrıca, string olmayan context değerlerini geçirmenize de olanak tanır.


Varsayılan geri dönüş değerini belirleme

Eğer React, üst ağaçta o belirli context sağlayan bir sağlayıcı bulamazsa, useContext() tarafından döndürülen context değeri, o context oluşturduğunuzda belirttiğiniz varsayılan değer ile aynı olacaktır:

const ThemeContext = createContext(null);

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

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

const ThemeContext = createContext('light');

Bu şekilde, yanlışlıkla uygun bir sağlayıcı olmadan bazı bileşenleri oluşturursanız, kırılmaz. Ayrıca, bileşenlerinizin test ortamında birçok sağlayıcı ayarlamadan iyi çalışmasına yardımcı olur.

Aşağıdaki örnekte “Temayı değiştir” butonu her zaman açık renkli olarak görüntülenir çünkü herhangi bir tema context’i sağlayıcısı dışında yer alır ve varsayılan context teması 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 kısmı için context’i farklı bir değerle sağlayan bir sağlayıcıya sararak, context’i değiştirebilirsiniz.

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

İhtiyacınız olan kadar sağlayıcıları iç içe yerleştirip geçersiz kılabilirsiniz.

Bazı örnekleri deneyin

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

Burada Footer içindeki 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 bir JavaScript nesnesidir ve bunlardan biri bir fonksiyondur. MyApp yeniden render edildiğinde (örneğin, bir rota güncellendiğinde) bu, farklı bir fonksiyona işaret eden farklı bir nesne olacaktır, bu nedenle derin ağaçta useContext(AuthContext) çağıran tüm bileşenlerin de yeniden render edilmesi gerekecektir.

Daha küçük uygulamalarda, bu bir sorun değildir. Ancak, currentUser gibi altta yatan veriler değişmediyse, bunları yeniden render etmek gerekli değildir. React’ın bu gerçekten faydalanabilmesine yardımcı olmak için, login fonksiyonunu useCallback ile sarmalayabilir 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>bu bileşeni render ediyorsunuz. SomeContext.Provider‘ı useContext() çağıran bileşenin üstüne ve dışına taşıyın.
  2. Bileşeninizi SomeContext.Provider ile sarmalamayı unuttunuz veya düşündüğünüzden farklı bir yerde yerleştirdiniz. React DevTools kullanarak hiyerarşinin doğru olup olmadığını kontrol edin.
  3. Sembolik bağlantılar kullanıyorsanız veya başka bir nedenle sağlayan bileşenin gördüğü SomeContext‘ın, okuyan bileşenin gördüğü SomeContext‘tan farklı olmasına neden olan bir yapılandırma sorunu ile karşılaşabilirsiniz. Bu, window.SomeContext1 ve window.SomeContext2 gibi global değişkenlere atayarak ve ardından konsolda window.SomeContext1 === window.SomeContext2 gibi bir kontrol yaparak doğrulayabilirsiniz. Eğer aynı değillerse, yapılandırma sorununu düzeltin.

Default değer farklı olsa da her zaman context’den undefined değerini alıyorum

Ağacınızda value belirtmeksizin bir sağlayıcı olabilir:

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

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

value belirtmeyi unutursanız, sanki value={undefined} geçirmişsiniz gibi davranılır.

Ayrıca, farklı bir özellik adı yanlışlıkla kullanmış da olabilirsiniz:

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

Bu durumlarda, React tarafından konsolda bir uyarı görmeniz gerektiğini unutmayın. Bunları düzeltmek için özelliği value olarak adlandırın:

// ✅ value özelliğini kullanarak geçirme
<ThemeContext.Provider value={theme}>
<Button />
</ThemeContext.Provider>

Önemli bir not olarak, varsayılan değerinizin (createContext çağrısındaki defaultValue) yalnızca hiçbir eşleşen sağlayıcı yoksa kullanılacağına dikkat edin. Alt ağaçta bir <SomeContext.Provider value={undefined}> bileşeni varsa, useContext(SomeContext) çağrısını yapan bileşen undefined olarak context değerini alacaktır.