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.


Murat Bilginer
21 Şubat 1992'de doğdum. Endüstri Mühendisi olarak lisansımı 2016 yılında tamamladım. Industryolog Akademi - NGenius oluşumlarının kurucusuyum. Şu anda kendi şirketim Brainy Tech ile Web ve Mobil Geliştirme, AWS, Google Cloud Platform Sistemleri için DevOps, Big Data Analiz ve Görselleştirme hizmetleri sunmakta ve Online Eğitimler vermekteyiz.