Merhabalar.
Bu yazımla beraber useContext Hook’unu başlangıç seviyesinde kullanmaya giriş yapacağız.
Bunun için yeni bir proje oluşturuyorum. Proje klasörümün ismi theme-dark-light olacak.
src içinde Components diye bir klasör, onun için Theme diye bir component klasörü ve içine Theme.jsx ve Theme.css dosyalarımı oluşturdum.
Projenin Amacı
Projeyle amacımız, uygulamada header’a bir dart/light butonu koyacağız, tıklanmasına göre tema dark ya da light olarak güncellenecek.
Sonuçta ben bunu bir state ile yöneteceğim.
Bir component’e bağlı yazarsam, çok sayfamın olduğu bir web uygulamamda her yeni sayfaya geçildiğinde, bu state’i propslarla ya da farklı yöntemlerle taşımam gerekirdi.
Ancak bu çok mantıklı gözükmüyor. Her sayfam için aynı kodları tekrarlamam ve değişkeni oradan oraya taşımam gerek.
useContext
Burada React geliştiricileri bize şunu diyor, biz sizin için useContext isminde bir Hook yazdık.
Siz bir değişkenin değeri her an istenilen yerden ulaşılsın istiyorsanız bu context ile bir sarmalayıcı element oluşturun. Ana component’inizi bu context ile sarmalayın ve bu oluşturduğunuz contex’in value property’sine taşımak istediğiniz değişkenleri gönderin.
Böylece bu state’e nerede ulaşmak ve hangi işlemi yaptırmak istiyorsanız kolayca yaptırabilirsiniz diyor.
Şimdi bu konu için geliştirdiğim uygulamanın kodlarını sizlerle paylaşıyorum.
Bunları aynen yerleştirin sonra kodları açıklayarak devam edelim.
index.js
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
export const ThemeContext = React.createContext();
const Root = () => {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<App />
</ThemeContext.Provider>
);
};
ReactDOM.render(<Root />, document.getElementById('root'));
App.js
import './App.css';
import Theme from './Components/Theme/Theme';
function App() {
return (
<Theme />
);
}
export default App;
Theme.jsx
import React, { Fragment, useContext } from 'react';
import './Theme.css';
import { ThemeContext } from '../../index';
const Theme = () => {
const { theme, setTheme } = useContext(ThemeContext);
const changeTheme = () => {
// Toggle between 'light' and 'dark' theme
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<Fragment>
<header className={`${theme}`}>
<nav>
<div className="logo">BrainTech</div>
<ul>
<li>Home</li>
<li>Products</li>
<li>About</li>
<li>Contact</li>
</ul>
<button onClick={changeTheme}>🌙</button>
</nav>
</header>
<div className={`hero ${theme}`}>
<h1>Welcome to our Technology Company</h1>
<p>We provide high quality tech solutions for your business.</p>
</div>
</Fragment>
);
};
export default Theme
Theme.css
/* Common styles */
header {
padding: 1em;
}
header nav {
display: flex;
align-items: center;
}
header nav .logo {
margin-right: auto;
}
header nav ul {
list-style-type: none;
padding: 0;
display: flex;
justify-content: space-around;
flex-grow: 1;
}
header nav button {
margin-left: 1em;
}
button{
padding: 0.5em 1em;
border: none;
border-radius: 5px;
background-color: #333;
color: #f5f5f5;
cursor: pointer;
}
.dark button:hover {
background-color: #533838;
color: #333;
}
.hero {
height: 100vh;
background-size: cover;
background-position: center;
padding: 50px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #333;
color: #f5f5f5;
}
.hero h1 {
font-size: 2.5em;
}
.hero p {
font-size: 1.2em;
}
/* Light theme styles */
.light button {
background-color: #f5f5f5;
color: #333;
}
.light button:hover {
background-color: #533838;
color: #f5f5f5;
}
.light {
background-color: #f5f5f5;
color: #333;
}
.light header {
background-color: #fff;
color: #333;
}
.light .hero {
background-color: #f5f5f5;
color: #333;
}
/* Dark theme styles */
.dark {
background-color: #333;
color: #f5f5f5;
}
.dark header {
background-color: #333;
color: #f5f5f5;
}
.dark .hero {
background-color: #333;
color: #f5f5f5;
}
Create Context
index.js tüm componentleri sarmaladığımız, App component’ini çağıran dosyam olduğu için Context elementimi burada oluşturacağım.
Bu oluşturduğum Context diğer componentler tarafından istediğimde çağrılacağı için index içindeki Root fonksiyonumuzun dışında oluşturulmalı ve export edilmeli.
Burada useState kullanacağım için ve useState react component fonksiyonları içinde kullanılabildiği için normalde bize verilen index.js dosyasının yapısını bir component fonksiyonuna çevirdim. Render ederken Root component’ini verdik.
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
export const ThemeContext = React.createContext();
const Root = () => {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<App />
</ThemeContext.Provider>
);
};
ReactDOM.render(<Root />, document.getElementById('root'));
ThemeContext Oluştur
export const ThemeContext = React.createContext();
Bu kod bir React uygulamasında kullanılan bir tema bağlamını oluşturuyor. React.createContext()
fonksiyonu, bir bağlam nesnesi oluşturur. Bu bağlam nesnesi, bir bileşen ağacındaki bileşenlere belirli bir değeri paylaşma mekanizması sağlar.
Bu durumda, bir tema bağlamı oluşturuluyor. Bu bağlam, uygulama genelinde temayla ilgili bilgileri paylaşmak için kullanılabilir.
useContext İle Taşınacak Değişkenleri Oluştur
Bunun için bir useState oluşturuyorum. Başlangıç değeri dark’dır.
const [theme, setTheme] = useState('dark');
ThemeContext İle App Component’ini Sarmala
App component’ini oluşturduğumuz ThemeContext ile sarmalayacağım.
<ThemeContext.Provider value={{ theme, setTheme }}>
<App />
</ThemeContext.Provider>
Bu bağlam nesnesi genellikle bir <ThemeContext.Provider>
bileşeni içinde kullanılır. <ThemeContext.Provider>
bileşeni, bağlamdaki değeri tüm iç bileşenlere ileten bir bileşendir. Bu sayede, uygulama genelinde tema bilgilerini paylaşabilir ve temaya bağlı olarak bileşenlerin görünümünü değiştirebilirsiniz.
Burada provider’ım sayesinde onun value property’si ile iletmek istediğim değişkenleri yolluyorum. Burada değer değişkenlerini gönderebileceğim gibi direkt fonksiyon isimlerini de gönderebilirim. Sonrasında bu fonksiyona ulaşıp işlem yaptığımda burada state’i etkileyecek.
Context’i oluşturduk. Takip edeceğimiz değer hazır sonra ana component’i bir provider nesnesi ile context’imiz ile sarmaladık. Bu context’e value ile iletmek istediğimiz değerleri gönderdik.
Artık Theme.jsx kodlarımıza bakabiliriz.
import React, { Fragment, useContext } from 'react';
import './Theme.css';
import { ThemeContext } from '../../index';
const Theme = () => {
const { theme, setTheme } = useContext(ThemeContext);
const changeTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<Fragment>
<header className={`${theme}`}>
<nav>
<div className="logo">BrainTech</div>
<ul>
<li>Home</li>
<li>Products</li>
<li>About</li>
<li>Contact</li>
</ul>
<button onClick={changeTheme}>🌙</button>
</nav>
</header>
<div className={`hero ${theme}`}>
<h1>Welcome to our Technology Company</h1>
<p>We provide high quality tech solutions for your business.</p>
</div>
</Fragment>
);
};
export default Theme
Import useContext Hook
Context ile bize sağlanan değişkenlere erişmek istediğim yerde useContext Hook’unu import etmem gerekir.
import React, { Fragment, useContext } from 'react';
Import ThemeContext
import { ThemeContext } from '../../index';
useContext Oluştur
useContext aşağıdaki gibi oluşturulur.
index içinde export ettiğim ThemeContext’i burada useContext’e bağlam olarak vereceğiz.
Yani oluşturduğum useContext Hook’u şunu bilecek, ben ThemeContext ile oluşturulan context’e erişip value’larını alacağım.
const { theme, setTheme } = useContext(ThemeContext);
value ile theme değişkeni ve setTheme fonksiyonunu göndermiştik bunu yakaladık.
Aşağıdaki butonun onClick event’ine changeTheme isminde bir fonksiyon bağladım. Butona tıkladıkça fonksiyon çalışacak.
<button onClick={changeTheme}>🌙</button>
changeTheme Fonksiyonu
changeTheme fonksiyonu useContext sayesinde ulaştığımız setTheme fonksiyonu ile yine useContext ile eriştiğimiz theme state’ini güncelliyor.
light durumda ise dark olarak güncelle, dark ise light olarak güncelle diyoruz.
const changeTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
Light ve dark durumlarının css’leri yazıldı. Dosyasından kontrol edebilirsiniz.
Bu theme değişkenin ismini className olarak kullanıyoruz. Bu sayede sayfamın teması güncelleniyor.
<header className={`${theme}`}>
<nav>
<div className="logo">BrainTech</div>
<ul>
<li>Home</li>
<li>Products</li>
<li>About</li>
<li>Contact</li>
</ul>
<button onClick={changeTheme}>🌙</button>
</nav>
</header>
<div className={`hero ${theme}`}>
<h1>Welcome to our Technology Company</h1>
<p>We provide high quality tech solutions for your business.</p>
</div>
Aşağıda gördüğünüz gibi. Header’a theme değişkeni değeri light ise light, dark ise dark sınıfı uygulanıyor.
<header className={`${theme}`}>
Bu useContext sayesinde bu uygulamada 10 tane component oluştursak ve orada da elementler light ve dark durumuna göre güncellenecekse doğrudan theme değişkenini çekip className olarak verebiliriz.
Uygulama Test
En basit haliyle useContext’i kullanmayı öğrendik.
Bir sonraki yazımda görüşmek üzere.