useContext
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 öncecreateContext
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şendeki
useContext()
çağrısı, aynı bileşenden dönen sağlayıcılardan etkilenmez. İlgili<Context>
useContext()` çağrısını yapan bileşenin üstünde olmalıdır. - React, farklı bir
değer
alan sağlayıcıdan başlayarak belirli bir bağlamı kullanan tüm çocukları otomatik olarak yeniden işler. Önceki ve sonraki değerlerObject.is
karşılaştırması ile karşılaştırılır. Yeniden oluşturma işlemlerininmemo
ile atlanması, çocukların yeni bağlam değerleri almasını engellemez. - Derleme sisteminiz çıktıda yinelenen modüller üretiyorsa (ki bu sembolik bağlantılarda olabilir), bu durum bağlamı bozabilir. Bir şeyi bağlam yoluyla iletmek, yalnızca bağlamı sağlamak için kullandığınız
SomeContext
ve onu okumak için kullandığınızSomeContext
,===
karşılaştırmasıyla belirlendiği gibi tam olarak aynı nesne ise ç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 value="dark">
<Form />
</ThemeContext>
);
}
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.
import { createContext, useContext } from 'react'; const ThemeContext = createContext(null); export default function MyApp() { return ( <ThemeContext value="dark"> <Form /> </ThemeContext> ) } 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 value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext>
);
}
Artık sağlayıcı içerisindeki herhangi bir Button
, güncel theme
değerini alacaktır. setTheme
i ç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.
Ö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 value={theme}> <Form /> <label> <input type="checkbox" checked={theme === 'dark'} onChange={(e) => { setTheme(e.target.checked ? 'dark' : 'light') }} /> Use dark mode </label> </ThemeContext> ) } 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 value={theme}> <Form /> </ThemeContext> <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 value="dark">
...
<ThemeContext value="light">
<Footer />
</ThemeContext>
...
</ThemeContext>
İhtiyacınız olduğu kadar çok sağlayıcıyı iç içe yerleştirebilir ve geçersiz kılabilirsiniz.
Ö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 value="dark"> <Form /> </ThemeContext> ) } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> <ThemeContext value="light"> <Footer /> </ThemeContext> </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 value={{ currentUser, login }}>
<Page />
</AuthContext>
);
}
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 value={contextValue}>
<Page />
</AuthContext>
);
}
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:
<SomeContext>
öğesiniuseContext()
öğesini çağırdığınız bileşenle aynı bileşende (veya altında) oluşturuyorsunuz.<SomeContext>
öğesiniuseContext()
öğesini çağıran bileşenin üstüne ve dışına taşıyın.- Bileşeninizi
<SomeContext>
ile sarmayı unutmuş ya da ağacın düşündüğünüzden farklı bir bölümüne koymuş olabilirsiniz. Hiyerarşinin doğru olup olmadığını React DevTools. kullanarak kontrol edin - Araçlarınızda, sağlayan bileşen tarafından görülen
SomeContext
ile okuyan bileşen tarafından görülenSomeContext
in iki farklı nesne olmasına neden olan bir derleme sorunuyla karşılaşıyor olabilirsiniz. Örneğin, sembolik bağlantılar kullanıyorsanız bu olabilir. Bunuwindow.SomeContext1
vewindow.SomeContext2
gibi globallere atayarak ve ardından konsoldawindow.SomeContext1 === window.SomeContext2
olup olmadığını kontrol ederek doğrulayabilirsiniz. Aynı değillerse, bu sorunu derleme aracı düzeyinde 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:
// 🚩 İşe yaramıyor: değer desteği yok
<ThemeContext>
<Button />
</ThemeContext>
value
belirtmeyi unutursanız, value={undefined}
geçmiş gibi davranır .
Yanlışlıkla farklı bir özellik adı kullanmış da olabilirsiniz:
// 🚩 Çalışmıyor: prop “değer” olarak adlandırılmalıdır
<ThemeContext theme={theme}>
<Button />
</ThemeContext>
Her iki durumda da konsolda React uyarısı görmelisiniz. Bunları düzeltmek için prop’u value
olarak adlandırın:
// ✅ Değer prop'unu geçirme
<ThemeContext value={theme}>
<Button />
</ThemeContext>
CreateContext(defaultValue)
çağrınızdan gelen [varsayılan değerin] (#specifying-a-fallback-default-value) yalnızca yukarıda eşleşen bir sağlayıcı yoksa kullanılır. Üst ağacın herhangi bir yerinde bir <SomeContext value={undefined}>
bileşeni varsa, useContext(SomeContext)
çağrısını yapan bileşen *bağlam değeri olarak undefined
alır.