React'in Context API'sine Giriş
Yayınlanan: 2022-03-10Bu eğitim için, kancalar hakkında adil bir anlayışa sahip olmalısınız. Yine de, başlamadan önce, bu makalede ne olduklarını ve kullanacağımız kancaları kısaca tartışacağım.
React Dokümanlarına göre:
“ Kancalar , React 16.8'deki yeni bir eklentidir. Bir sınıf yazmadan durum ve diğer React özelliklerini kullanmanıza izin veriyorlar.”
Temel olarak bir React kancası budur. İşlevsel bileşenlerimizde durum, referanslar ve diğer React özelliklerini kullanmamıza olanak tanır.
Bu yazıda karşılaşacağımız iki kancayı tartışalım.
useState
Kancası
useState kancası , durumu işlevsel bileşenlerimizde kullanmamıza izin verir . useState
kancası, durumumuzun ilk değerini tek argüman olarak alır ve iki elemanlı bir dizi döndürür. İlk eleman durum değişkenimizdir ve ikinci eleman durum değişkeninin değerini güncellemeyi kullanabileceğimiz bir fonksiyondur.
Aşağıdaki örneğe bir göz atalım:
import React, {useState} from "react"; function SampleComponent(){ const [count, setCount] = useState(0); }
Burada count
bizim durum değişkenimizdir ve başlangıç değeri 0
iken setCount
, count değerini güncellemek için kullanabileceğimiz bir fonksiyondur.
useContext
Hook
Bunu makalede daha sonra tartışacağım ama bu kanca temelde bir bağlamın değerini tüketmemize izin veriyor . Bunun gerçekte ne anlama geldiği makalenin ilerleyen bölümlerinde daha belirgin hale gelecektir.
İplik Çalışma Alanları
Yarn çalışma alanları, monolitik bir depo (monorepo) kullanarak proje kod tabanınızı düzenlemenize izin verir. React, monorepo olan ve bu amaca ulaşmak için Yarn çalışma alanlarını kullanan açık kaynaklı bir projenin güzel bir örneğidir. İlgili bir makaleyi okuyun →
Neden Bağlam API'sine İhtiyacımız Var?
React uygulamamız için açık mod ve karanlık mod arasında geçiş yapan bir "tema değiştirici" bileşeni oluşturmak istiyoruz. Her bileşenin mevcut tema moduna erişimi olması gerekir, böylece uygun şekilde şekillendirilebilirler.
Normalde, aksesuarlar aracılığıyla tüm bileşenlere mevcut tema modunu sağlar ve mevcut temayı state
kullanarak güncellerdik:
import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div> <Text theme= "blue" /> <h1>{theme}</h1> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
Yukarıdaki kod örneğinde, bir h1
öğesi oluşturan bir Metin Bileşeni oluşturduk. h1
öğesinin rengi mevcut tema moduna bağlıdır. Şu anda, tema mavidir. state
kullanarak blue
ve red
temalar arasında geçiş yapabiliriz.
useState
kancasını kullanarak “theme” adında bir durum oluşturacağız. useState
kancası, temanın geçerli değerini ve temayı güncellemek için kullanabileceğimiz bir işlevi döndürür.
O halde tema durumumuzu oluşturalım:
const [theme, setTheme] = React.useState("blue");
Ayrıca App
bileşenimize bir düğme öğesi ekleyeceğiz. Bu düğme temaları değiştirmek için kullanılacak ve bir tıklama olay işleyicisine ihtiyacı var. Öyleyse, click olay işleyicisini şöyle yazalım:
const onClickHandler = () => { setTheme(); }
Şimdi, mevcut tema Blue
ise yeni temayı Red
olarak ayarlamak istiyoruz ve bunun tersi de geçerlidir. Bir if
ifadesi kullanmak yerine, bunu yapmanın daha uygun bir yolu JavaScript'teki üçlü operatörün yardımıdır.
setTheme( theme === "red"? "blue": "red");
Şimdi, onClick
işleyicimizi yazdık. Bu düğme öğesini App
bileşenine ekleyelim:
<button onClick = {onClickHandler}>Change theme</button>
Ayrıca Text bileşeninin theme props değerini de theme durumuna değiştirelim.
<Text theme={theme}/>
Şimdi, buna sahip olmalıyız:
import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function App() { const[theme, setTheme] = React.useState("red"); const onClickHandler = () => { setTheme( theme === "red"? "blue": "red"); } return ( <div> <Text theme={theme}/> <button onClick = {onClickHandler}>Change theme</button> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
Artık iki temamız arasında geçiş yapabiliriz. Ancak, bu çok daha büyük bir uygulama olsaydı, temayı derinlemesine iç içe bileşenlerde kullanmak zor olurdu ve kod hantal hale gelir.
Bağlam API'sine Giriş
Bağlam API'sini tanıtmama izin verin. React belgelerine göre:
"Bağlam, verileri her düzeyde manuel olarak aşağı aktarmak zorunda kalmadan bileşen ağacından geçirmenin bir yolunu sağlar."
Daha derinlemesine bir tanım için, belirli verileri bileşen ağacının tamamında, o bileşen ne kadar iç içe geçmiş olursa olsun tüm bileşenler için kullanılabilir hale getirmeniz için bir yol sağlar.
Şu örneğe bakalım:
const App = () => { return( <ParentComponent theme = "light"/> ); } const ParentComponent = (props) => ( <Child theme = {props.theme} /> ) const Child = (props) => ( <Grandchild theme = {props.theme} /> ) const Grandchild = (props) => ( <p>Theme: {props.theme}</p> )
Yukarıdaki örnekte, uygulama theme
, Theme adlı ParentComponent
bir props kullanarak belirttik. GrandChild
bileşeni olan ihtiyaç duyulan yere ulaşmak için bu aksesuarları bileşen ağacındaki tüm bileşenlere geçirmemiz gerekiyordu. ChildComponent
tema aksesuarlarıyla hiçbir ilgisi yoktu, sadece bir aracı olarak kullanıldı.
Şimdi GrandChild
bileşeninin en üstteki örnekte olduğundan daha derin bir şekilde iç içe olduğunu hayal edin. Tema aksesuarlarını burada yaptığımız gibi geçmemiz gerekecekti ki bu hantal olurdu. Context
çözdüğü sorun budur. Context
ile, bileşen ağacındaki her bileşen, bağlamımıza koymaya karar verdiğimiz tüm verilere erişebilir.
Context
Başlayalım
Makalenin başında oluşturduğumuz tema değiştirme düğmesini Context API ile çoğaltmanın zamanı geldi. Bu sefer tema değiştiricimiz ayrı bir bileşen olacak. Context
kullanarak React uygulamamızın temasını değiştiren bir ThemeToggler
bileşeni oluşturacağız.
Öncelikle React uygulamamızı başlatalım. (Ben create-react-app
kullanmayı tercih ediyorum ama siz istediğiniz yöntemi kullanabilirsiniz.)
React projenizi başlattıktan sonra /src
klasörünüzde ThemeContext.js adlı bir dosya oluşturun. Ayrıca /context
adında bir klasör oluşturabilir ve isterseniz ThemeContext dosyanızı oraya yerleştirebilirsiniz.
Şimdi, devam edelim.
Bağlam API'nizi Oluşturma
Tema bağlamımızı ThemeContext.js dosyamızda oluşturacağız.
Bir bağlam oluşturmak için, bir bağlam nesnesi oluşturan React.createContext
kullanırız. Herhangi bir şeyi argüman olarak React.createContext
. Bu durumda, mevcut tema modu olan bir dizeye geçeceğiz. Şimdi mevcut tema modumuz “hafif” tema modudur.
import React from "react"; const ThemeContext = React.createContext("light"); export default ThemeContext;
Bu içeriği tüm React bileşenlerimiz için kullanılabilir hale getirmek için bir Sağlayıcı kullanmalıyız. Sağlayıcı nedir? React belgelerine göre, her bağlam nesnesi, tüketen bileşenlerin bağlam değişikliklerine abone olmasına izin veren bir Sağlayıcı React bileşeniyle birlikte gelir . İçeriğin diğer bileşenler tarafından tüketilmesine izin veren sağlayıcıdır. Bununla birlikte, sağlayıcımızı oluşturalım.
App.js dosyanıza gidin. Sağlayıcımızı oluşturmak için ThemeContext
içe aktarmalıyız.
ThemeContext
içe aktarıldıktan sonra, App
bileşenimizin içeriğini ThemeContext.Provider
etiketleri içine almalı ve ThemeContext.Provider
bileşenine, bileşen ağacımız için kullanılabilir kılmak istediğimiz verileri içerecek, value
adı verilen bir destek vermeliyiz.
function App() { const theme = "light"; return ( <ThemeContext.Provider value = {theme}> <div> </div> </ThemeContext.Provider> ); }
Yani artık “ışık” değeri tüm bileşenlerimizde mevcuttur (ki bunu birazdan yazacağız).
Tema Dosyamızı Oluşturmak
Şimdi hem açık hem de koyu temalarımız için farklı renk değerlerini içerecek tema dosyamızı oluşturacağız. /src
klasörünüzde Colors.js adlı bir dosya oluşturun.
AppTheme
AppTheme adında bir nesne oluşturacağız. Bu nesne, temalarımızın renklerini içerecektir. İşiniz bittiğinde, AppTheme
nesnesini şu şekilde dışa aktarın:
const AppTheme = { light: { textColor: "#000", backgroundColor: "#fff" }, dark: { textColor: "#fff", backgroundColor: "#333" } } export default AppTheme;
Şimdi farklı React bileşenlerimizi oluşturmaya başlama zamanı.
React Bileşenlerimizi Oluşturma
Aşağıdaki bileşenleri oluşturalım:
-
Header
-
ThemeToggler
-
MainWithClass
Header.jsx
import React from "react"; import ThemeToggler from "./ThemeToggler"; const headerStyles = { padding: "1rem", display: "flex", justifyContent: "space-between", alignItems: "center" } const Header = () => { return( <header style = {headerStyles}> <h1>Context API</h1> <ThemeToggler /> </header> ); } export default Header;
ThemeToggler.jsx
(Şimdilik sadece boş bir div
döndüreceğiz.)
import React from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { return( <div style = {themeTogglerStyle}> </div> ); } export default ThemeToggler;
Sınıf Tabanlı Bileşenlerle Bağlamı Tüketmek
Burada ThemeContext
değerini kullanacağız. Bildiğiniz gibi , React'te bileşen yazmak için iki yöntemimiz var: işlevler veya sınıflar aracılığıyla. Her iki yöntemde de bağlam kullanım süreci farklıdır, bu nedenle uygulamamızın ana bölümü olarak hizmet edecek iki bileşen oluşturacağız: MainWithClass
ve MainWithFunction
.
MainWithClass
ile başlayalım.
MainWithClass.jsx
ThemeContext
ve AppTheme
dosyalarımızı içe aktarmamız gerekecek. Bu yapıldıktan sonra, bir render yönteminden JSX'imizi döndüren bir sınıf yazacağız. Şimdi bağlamımızı tüketmeliyiz. Bunu sınıf tabanlı bileşenlerle yapmanın iki yöntemi vardır:
- İlk yöntem
Class.contextType
aracılığıyladır.
Bu yöntemi kullanmak için,ThemeContext
bağlam nesnesinicontextType
özelliğine atadık. Bundan sonra,this.context
kullanarak bağlam değerine erişebileceğiz. Buna herhangi bir yaşam döngüsü yönteminde ve hatta oluşturma yönteminde de başvurabilirsiniz.import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context]; return( <main></main> ); } }
contextType
özelliğineThemeContext
atadıktan sonra,currentTheme
değişkeninde mevcut theme nesnesini kaydettim.
Şimdi,currentTheme
değişkeninden renkleri alacağız ve bunları bazı işaretlemeleri biçimlendirmek için kullanacağız.render() { const currentTheme = AppTheme[this.context]; return ( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main>
Bu kadar! Ancak bu yöntem, yalnızca bir bağlam tüketmenizi sınırlar. - İkinci yöntem, bir Tüketici kullanımını içeren
ThemeContext.Consumer
. Her bağlam nesnesi ayrıca sınıf tabanlı bir bileşende kullanılabilen bir Tüketici Tepkisi bileşeniyle birlikte gelir. Tüketici bileşeni, bir çocuğu işlev olarak alır ve bu işlev bir React düğümü döndürür. Geçerli bağlam değeri, bu işleve bir bağımsız değişken olarak iletilir.
ŞimdiMainWithClass
bileşenimizdeki kodu bununla değiştirelim:class Main extends Component { constructor() { super(); this.state = { } } render(){ return( <ThemeContext.Consumer> { (theme) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } }
Gördüğünüz gibiThemeContext
“theme” adını verdiğimiz mevcut değerini kullandık ve o tema modu için renk değerlerini alıpcurrentTheme
değişkenine atadık. Bu yöntemle birden fazla Tüketici kullanabilirsiniz.
Bunlar, sınıf tabanlı bileşenlerle bağlam tüketmenin iki yöntemidir.
İşlevsel Bileşenlerle Bağlam Kullanmak
İşlevsel bileşenlerle bağlam tüketmek, sınıf tabanlı bileşenlerle yapmaktan daha kolay ve daha az sıkıcıdır. Bağlamı işlevsel bir bileşende kullanmak için useContext
adlı bir kanca kullanacağız.
ThemeContext
işlevsel bir bileşenle tüketmek şöyle görünür:
const Main = () => { const theme = useContext(ThemeContext); const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
Gördüğünüz gibi, tek yapmamız gereken, argüman olarak geçirilen ThemeContext
ile useContext
kullanmaktı.
Not : Sonuçları görebilmek için App.js dosyasında bu farklı bileşenleri kullanmanız gerekmektedir.
ThemeToggler
Bileşeniyle Güncelleme
Şimdi ThemeToggler
bileşenimiz üzerinde çalışacağız. Açık ve koyu temalar arasında geçiş yapabilmemiz gerekiyor. Bunu yapmak için ThemeContext.js dosyamızı düzenlememiz gerekecek. React.createContext
artık argüman olarak useState
kancasının sonucuna benzeyen bir nesne alacaktır.
const ThemeContext = React.createContext(["light", () => {}]);
React.createContext
işlevine bir dizi ilettik. Dizideki ilk öğe, geçerli tema modudur ve ikinci öğe, temayı güncellemek için kullanılacak işlevdir. Dediğim gibi, bu sadece bir useState
kancasının sonucuna benziyor, ancak tam olarak bir useState
kancasının sonucu değil.
Şimdi App.js dosyamızı düzenleyeceğiz. Sağlayıcıya iletilen değeri bir useState
kancasıyla değiştirmemiz gerekiyor. Şimdi Tema Bağlamımızın değeri, varsayılan değeri "hafif" olan bir useState
.
function App() { const themeHook = useState("light"); return ( <ThemeContext.Provider value = {themeHook}> <div> <Header /> <Main /> </div> </ThemeContext.Provider> ); }
ThemeToggler
Bileşenimizi Yazma
Şimdi ThemeToggler
bileşenimizi gerçekten yazalım:
import React,{useContext} from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { const[themeMode, setThemeMode] = useContext(ThemeContext); return( <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}> <span title = "switch theme"> {themeMode === "light" ? "" : "️"} </span> </div> ); } export default ThemeToggler;
Tema bağlamımızın değeri artık bir kanca olduğundan, ne zaman üzerinde useContext
, bir dizi döndürür. Yıkımı kullanarak, dizideki öğeleri yakalayabildik. Ardından ThemeToggler
için bir onClick
olay işleyicisi yazdık. Bu kodla, tema değiştirici tıklandığında, uygulamamızın temasını değiştirecektir.
Şimdi Main
bileşenimizin farklı sürümlerini düzenleyeceğiz.
MainWithClass
Bileşenimizi Düzenleme
-
MainWithClass
bileşenininClass.contextType
yöntemini kullanan sürümü:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context[0]]; return( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } }
-
ThemeContext.Consumer
yöntemini kullananMainWithClass
bileşeninin sürümü:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component { constructor() { super(); this.state = {} } render() { return ( <ThemeContext.Consumer> { ([theme]) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } } export default Main;
MainWithFunction
Bileşenimizi Düzenleme
MainWithFunction
Bileşeni aşağıdaki gibi düzenlenmelidir:
import React, { useContext } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; const Main = () => { const theme = useContext(ThemeContext)[0]; const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
Çözüm
Bu kadar! Context API kullanarak React uygulamamız için iki tema modu uygulamayı başardık.
Bu süreçte şunları öğrendik:
- Bağlam API'sinin ne olduğu ve çözdüğü sorun;
- Bağlam API'si ne zaman kullanılır;
-
Context
oluşturma ve hem işlevsel hem de sınıf tabanlı bileşenlerde tüketme.
SmashingMag'de Daha Fazla Okuma :
- Modern Web Uygulamalarında Stil Oluşturma
- Ionic And React ile Mobil Uygulamalar Oluşturma
- Web Paketi ve Çalışma Kutusu ile PWA Oluşturun
- MutationObserver API'sini Tanımak