Yeni Başlayanlar için React Rehberi

Kardel Rüveyda ÇETİN
29 min readMar 10, 2024

İnternetin sonsuz okyanusunda yolculuk etmek, zamanın akışına kapılmak gibidir. Her bir sayfa, birer gemi gibi, farklı deneyimler sunar ve her tıkladığınızda, yeni bir maceraya adım atmış olursunuz. Ancak, bu yolculukta rehberiniz olmadan kaybolmak kolaydır. İşte burada, yeni bir maceranın eşiğindeyiz ve bu sefer rotamız React’in büyülü dünyası. Gelin, kod okyanusunda ilk adımlarımızı atalım ve React ile unutulmaz bir yolculuğa çıkalım!

React Tarihçesi

Facebook’un web sitesindeki canlı güncellemeler ve hızlı kullanıcı etkileşimi, internetin dönüm noktalarından biri olarak kabul edilir. Ancak, bu tür dinamik web uygulamalarını geliştirmek, geleneksel web teknolojileriyle bazı zorluklarla karşılaşabilir. Bu zorlukları aşmak için, birçok geliştirici JavaScript framework’lerine başvurmuştur. Bu bağlamda, Facebook’un geliştirdiği ve kendi platformunda yaygın olarak kullandığı React, dikkatleri üzerine çekmiştir. React’ın öyküsü, sadece bir framework’ün ötesine geçen, bir endüstri standardı haline gelen bir serüvenin başlangıcını temsil ediyor. Facebook, zamanla gelişen ve büyüyen web platformunda, kullanıcı deneyimini sürekli olarak iyileştirmek için yenilikçi çözümler aramıştır. Bu çabalar, gerçek zamanlı güncellemelerin hızlı ve etkili bir şekilde yapılabilmesini sağlayacak bir sistem arayışına dönüşmüştür. İşte bu noktada, React devreye girer. Facebook’un kendi deneyimlerinden ve ihtiyaçlarından yola çıkarak geliştirilen React, dinamik ve kullanıcı dostu web uygulamaları oluşturmak için geliştiricilere güçlü bir araç sunar. Ancak, React’ın başarısı sadece Facebook’un kendi platformunda değil, aynı zamanda diğer büyük şirketler ve geliştiriciler arasında da hızla yayılmıştır. Örneğin, Instagram’ın Facebook tarafından satın alınması ve Instagram ekibinin React’ı keşfetmesi, bu framework’ün potansiyelini daha geniş bir kitleye tanıtmıştır. Benzer şekilde, Airbnb gibi öncü şirketlerin React’ı benimsemesi, bu teknolojinin endüstri standartları arasında yer almasını sağlamıştır. Bu gelişmelerin ışığında, JavaScript ve web geliştirme dünyasında, React’ın önemi ve etkisi giderek artmaktadır. Günümüzde, React sadece bir framework değil, aynı zamanda modern web uygulamalarının temel taşıdır.

React, JavaScript tabanlı bir açık kaynaklı frontend kütüphanesidir. Facebook tarafından 2013 yılında geliştirilmiştir. React, web uygulamalarının ön yüzünü oluşturmak için kullanılırken, React Native mobil uygulama geliştirmek için kullanılır. React’in temel yapıları üç ana bileşen üzerine kuruludur: komponentler, props ve state management.

  1. Komponentler: React uygulamalarında UI’yi parçalara bölmek için kullanılan yapıdır. Her bir komponent, belirli bir görevi yerine getirir ve tekrar kullanılabilir. Komponentler, birbirleriyle hiyerarşik bir yapı oluşturarak kompleks UI’leri kolayca oluşturmanıza olanak tanır.
  2. Props (Özellikler): Komponentler arasında veri iletişimini sağlamak için kullanılır. Bir komponent, diğer bir komponente veri iletmek için props adı verilen özellikleri kullanır. Bu, verilerin üst komponentten alt komponentlere aktarılmasını sağlar.
  3. State Management (Durum Yönetimi): Uygulama içindeki dinamik verilerin yönetimini sağlar. Örneğin, kullanıcı girişi gibi değişken verilerin tutulması ve güncellenmesi için kullanılır. React’te state management için Context API ve Redux gibi araçlar kullanılır.

React, JavaScript ve HTML bilgisine dayanır ve bu konularda temel bir anlayış gerektirir. Bu nedenle, React’i öğrenmeden önce JavaScript ve HTML konularında sağlam bir temel oluşturmanız önemlidir.

React.js öğrenmeli miyim ?

Web geliştirme alanında faaliyet gösteren biriyseniz, React’i öğrenmeniz gerektiğini söylemek oldukça doğru olacaktır. React, web ve mobil uygulamalar geliştirmek için güçlü bir araçtır ve React Native sayesinde aynı temel yapıyı kullanarak JavaScript kullanarak hem web hem de mobil uygulamalar oluşturabilirsiniz. Hem devasa web uygulamaları hem de popüler mobil uygulamalar, React ve React Native’in sunduğu olanaklardan yararlanarak başarıyla geliştirilmiştir.

Özellikle .NET geliştiricileri için, React’i öğrenmek mevcut yeteneklerini genişletebilir ve kariyerlerinde yeni fırsatlar yaratabilir. Dolayısıyla, React.js öğrenimini sizlere tavsiye ederim, çünkü bu size hem mevcut kariyerinizde yeni kapılar açabilir hem de gelecekteki projelerinizde daha etkili ve verimli olmanızı sağlayabilir.

React.js Kurulum Püf Noktaları ve Çalışma Ortamının Hazırlanması

  1. React geliştirme ortamını oluşturmak için ilk adım, Node.js’in kurulumudur. Node.js, JavaScript tabanlı uygulamalar geliştirmek için gereken çalışma zamanını sağlar.
  2. Daha sonra, Visual Studio Code gibi bir geliştirme ortamı seçilir. Bu gibi modern editörler, React uygulamalarını geliştirmek için zengin özellikler ve eklentiler sunar.(Ben de Visual Studio Code kullanıyorum ama Atom, Sublime Text gibi editörlerini de kullanabilirsiniz.)
  3. Visual Studio Code’un kurulumu tamamlandıktan sonra, Node.js ile birlikte gelen npm (Node Package Manager) kullanılarak geliştirme için gerekli paketler indirilir ve yönetilir.Node.js’yi indirdikten sonra bir terminal açıp node -v yazarak kurulup kurulmadığını kontrol edebilirsiniz.
  4. React projeleri için önemli olan bazı eklentiler ve araçlar da Visual Studio Code’a entegre edilir. Örneğin, “Simple React Snippets” ve “ES7 React/Redux/GraphQL/React-Native snippets” gibi eklentiler, hızlı kod yazmayı ve verimliliği artırmayı sağlar.
Simple React Snippets Eklentisi
ES7 React/Redux/GraphQL/React-Native Snippets Eklentisi

Bu adımlar, bir React projesinin başlangıç ​​aşamasında sağlam bir temel oluşturmak için gereklidir. Profesyonel bir geliştirme ortamı oluşturulması, daha verimli ve düzenli bir şekilde çalışmayı sağlar.

React Dev Tools Kurulumu

React Developer Tools, React uygulamalarını geliştirmek için bir tarayıcı eklentisidir. İşlevleri arasında React componentlerinin hiyerarşisini görüntüleme, component durumunu ve özelliklerini inceleme, performans analizi yapma ve daha fazlası bulunur.

  • React Developer Tools, uygulamanın component yapısını görsel olarak sunar.
  • Herhangi bir componentin durumunu ve özelliklerini inceleyebilirsiniz.
  • Componentin durumunu ve özelliklerini canlı olarak değiştirebilirsiniz.
  • Uygulamanın performansını izlemek ve optimize etmek için kullanılabilir.
  • Componentin kodunu hızlıca bulup düzenlemek için IDE’nizle senkronize olabilir.

Kurulum:

  • Chrome Web Mağazası’ndan React Developer Tools’ü indirip kurabilirsiniz.
  • Tarayıcınızda React uygulamasını açın. Tarayıcı araç çubuğunda “React” sekmesini bulun veya sağ tıklayarak “Inspect” menüsünden “React” sekmesini açın. React Developer Tools, uygulamanın component hiyerarşisini, durumunu, özelliklerini ve diğer bilgileri gösterecektir.

React Developer Tools, React uygulamalarını geliştirirken hızlı ve etkili bir şekilde hata ayıklama ve performans analizi yapmanıza olanak tanır.

React Projesi Oluşturma ve Dosya Yapısını İnceleme

React projesi açtığımızda içerisine gelen bazı dosyaların ne olduğunu, ne amaçla oluşturulduğunu ve yapısını mimarisini biraz sizlere anlatmak istiyorum.

Önceleri npx create-react-app diyerek projeler açılıyordu. Ancak yeni gelen güncelleme kullanarak React projelerini “Vite” ile açabiliyoruz. React projesi en popüler şekilde Vite ile açılıyor.

npm create vite@latest
Vite Kurulum Aşaması

Vite kullanarak yeni bir proje oluşturmak oldukça hızlı ve basittir. İlk adımda, Terminal’i açarak çalışma dizininize gidin ve ardından npm create vite@latest my-vite-project komutunu kullanarak yeni bir Vite projesi başlatabilirsiniz. Bu komut, projenizin temel yapılandırmasını oluşturmanıza olanak tanır. Proje oluşturulduktan sonra, projenizin dizinine giderek gerekli bağımlılıkları yüklemek için npm install komutunu çalıştırmak gerekir. Bu komut, proje için gerekli olan tüm paketleri yükleyerek node_modules klasörünü oluşturur. Daha sonra, geliştirme sunucusunu başlatmak için npm run dev komutunu kullanarak projenizi çalışır duruma getirebilirsiniz.

React.js Projesi Dosyalarındaki Detaylar

  • Proje, src (source) dizini altında organize edilmiştir. Bu dizindeki dosyalar proje kaynak kodlarını içerir.
  • App.jsx dosyası, bir React bileşenini içeren ana dosyadır.
  • App.css dosyası, stil tanımlarını içerir ve App.jsx dosyası tarafından kullanılır.
  • package.json dosyası, proje bağımlılıklarını (dependencies) ve çalıştırılabilir komutları içerir. Proje bağımlılıkları, npm install komutuyla yüklenir ve package.json altında listelenir.
  • App.jsx bileşeni, JSX (JavaScript XML) sözdizimini kullanarak HTML ve JavaScript'i birleştirir.
  • Bileşenler, export anahtar kelimesiyle dışa aktarılır ve diğer dosyalardan içe aktarılabilir hale gelir.
  • Stil tanımları, App.css dosyasında bulunur ve App.jsx dosyası tarafından içeri aktarılır.CSS dosyası, bileşenlerin görünümünü belirlemek için kullanılır.
  • index.html dosyası, React uygulamasının başlangıç noktasıdır. index.html dosyası, root adında bir div içerir. Bu div, React uygulamasının yerleştirileceği yerdir.
  • main.js dosyası, root elementini seçer ve App bileşenini bu elementin içine render eder.
  • React projeleri, bileşenlerin birbirine bağlandığı bir yapıya sahiptir. Bileşenler, JSX kullanılarak oluşturulur ve birbirlerine import ve export anahtar kelimeleriyle bağlanır.

React projelerini yapılandırmak için önerilen bir yol var mı?

React projelerinde dosya yapısını organize etmek için tek bir standart bulunmamakla birlikte, genellikle tercih edilen birkaç yaygın yaklaşım mevcuttur.

Özelliklere veya rotalara göre gruplandırma

Projeleri yapılandırmak için kullanılan yaygın yöntemlerden biri; CSS, JS ve testleri özellik veya rotalara göre gruplanan klasörlerin içine beraber koymaktır.

common/
Avatar.js
Avatar.css
APIUtils.js
APIUtils.test.js
feed/
index.js
Feed.js
Feed.css
FeedStory.js
FeedStory.test.js
FeedAPI.js
profile/
index.js
Profile.js
ProfileHeader.js
ProfileHeader.css
ProfileAPI.js

React projelerinde dosya yapısını düzenlemek için tek bir evrensel standart bulunmamaktadır. Bu nedenle, özelliklerinizi ve ayrıntı derecesini belirlemek size kalmıştır. Eğer bir üst düzey klasörler listesi oluşturmakta zorlanırsanız, kullanıcılarınıza ürününüzün hangi ana bölümlerden oluştuğunu sorabilir ve akıllarındaki modeli bir taslak olarak kullanabilirsiniz.

Dosya türüne göre gruplandırma

Projeleri organize etmenin başka bir yaygın yöntemi de benzer dosyaları bir araya getirmektir.

api/
APIUtils.js
APIUtils.test.js
ProfileAPI.js
UserAPI.js
components/
Avatar.js
Avatar.css
Feed.js
Feed.css
FeedStory.js
FeedStory.test.js
Profile.js
ProfileHeader.js
ProfileHeader.css

Bazı insanlar, bileşenleri uygulamadaki rollerine göre farklı klasörlere ayırarak daha ileri gidebilirler. Örneğin, Atomic Design, bu ilkeye dayalı bir tasarım metodolojisidir. Bu tür metodolojilerin katı kurallarla değil, yardımcı örneklerle takip edilmesi daha verimli olabilir.

Çok fazla iç içe koymaktan kaçının

JavaScript projelerinde klasörleri çok derinleştirmenin birçok olumsuz yönü bulunmaktadır. Klasörler arasında bağlantıları kurmak veya dosyalar taşındığında bu bağlantıları güncellemek giderek zorlaşabilir. Derin bir dizin yapısı kullanmak için net bir sebep yoksa, kendi projeniz için en fazla üç ya da dört iç içe klasör kullanmak gibi bir sınırlama düşünülebilir. Ancak, bu sadece bir öneridir ve projenizin gereksinimlerine uygun olmayabilir.

Çok fazla düşünmeyin

Bir projeye yeni başlıyorsanız, dizin yapısı üzerine çok fazla zaman harcamamanız önemlidir. Yukarıdaki yaklaşımlardan birini seçin veya kendi yönteminizi getirin ve kod yazmaya başlayın! Biraz gerçek kod yazdıktan sonra, bu konuyu muhtemelen tekrar düşünmek isteyeceksinizdir.

Eğer tamamen çıkmaza girdiyseniz, tüm dosyaları tek bir klasörde tutarak başlayın. Projeniz zamanla büyüdükçe, hangi dosyaların birlikte sıkça düzenlendiğini fark edeceksiniz. Genellikle birlikte değiştirilen dosyaları birbirlerine yakın tutmak iyi bir fikirdir; bu, “ortak yerleşim” prensibi olarak adlandırılır.

Projeler büyüdükçe, genellikle yukarıdaki yaklaşımların bir karışımı uygulanır. Yani başlangıçta “doğru” olanı seçmek çok önemli değildir.

Nedir bu JSX?

Normalde, JSX kullanmadan önce, genellikle ne yapardık? Şimdi bu sorulara cevap arayacağız ve return ifadesi üzerine JavaScript kodlarını yazarken return ifadesi içine ise HTML kodlarını yazacağız. JSX’in hedefi ise JavaScript kodlarını HTML içine yerleştirip serpiştirmeyi hedeflemektir. Süslü Parantezlerin parantezlerin kullanımı, JSX’in temel özelliklerinden biridir.

JSX kullanırken, süslü parantezler içine JavaScript kodlarını yazarak HTML içine yerleştirebilirsiniz. Örneğin, x değişkenini süslü parantez içine yazdığınızda, JSX bu değişkeni bir JavaScript kodu olarak algılar. Bu sayede, JavaScript kodunu HTML ile birleştirerek kullanabilirsiniz. JSX’in amacı, HTML ile JavaScript’i bir araya getirerek daha kompakt ve yönetilebilir bir yapı oluşturmaktır. Bu yapının kullanımı, örneğin matematiksel işlemler veya mantıksal operasyonlar gibi birçok farklı alanda kullanılabilir.

JSX kullanırken, süslü parantezler içine JavaScript kodlarını yazabilirsiniz. Örneğin, bir dizi içinde döngü yaparak her bir elemanı alıp işleyebilir ve HTML içinde kullanabilirsiniz. Bu şekilde, dinamik ve esnek bir yapı elde edersiniz.

import React from 'react';

function NumbersComponent () {
const numbers = [1, 2, 3, 4, 5];

return (
<div>
<h1>Çift Sayılar:</h1>
<ul>
{numbers.map((number, index) => {
if (number % 2 === 0) {
return <li key={index}>{number}</li>;
} else {
return null; // Tek sayıları görmezden gel
}
})}
</ul>
</div>
);
}

export default NumbersComponent;

CSS özellikleri vermek için, JSX içinde stil etiketi kullanabilirsiniz. Bu stil etiketini kullanırken, süslü parantezler içine CSS kodlarını yazabilirsiniz. Bu sayede, HTML elementlerine kolayca CSS özellikleri ekleyebilirsiniz.

const App = () => {
return (
<div>
<h1 style={{ color: 'blue', fontSize: '24px' }}>Merhaba, Dünya!</h1>
<p style={{ backgroundColor: 'lightgray', padding: '10px' }}>Bu bir CSS örneğidir.</p>
</div>
);
}

export default App;

Component yapısını anlayalım!

React componentleri, kullanıcı arayüzünün farklı parçalarını temsil eden ve kendi içinde bağımsız çalışabilen JavaScript fonksiyonları veya sınıflarıdır. Bir React componenti, JSX (JavaScript XML) sözdizimi kullanılarak oluşturulur ve genellikle birbirine bağımlı olan HTML, CSS ve JavaScript kodlarını içerir.

Component Oluşturma: React’te bir component oluşturmak oldukça basittir. Yeni bir component oluşturmak için, genellikle src/components gibi bir klasör yapısı kullanılır ve bu klasör altında yeni bir JavaScript dosyası oluşturulur. Dosyanın içeriği, bir fonksiyon veya sınıf tanımlaması içerir ve JSX kullanılarak componentin görüntüsü belirlenir.

import React from 'react';

function Login() {
return (
<div>
<input type="text" placeholder="Kullanıcı Adı" />
<input type="password" placeholder="Şifre" />
<button>Giriş Yap</button>
</div>
);
}

export default Login;

Oluşturulan component, başka bir component veya uygulama dosyası içinde çağrılabilir. Componentler, import edilerek ve JSX içine yerleştirilerek kullanılır. Bu sayede, uygulamanın farklı bölümlerinde aynı componenti birden fazla kez kullanmak mümkün olur.

import React from 'react';
import Login from './components/Login';

function App() {
return (
<div>
<h1>Merhaba, React!</h1>
<Login />
</div>
);
}

export default App;

React componentleri, modüler ve yeniden kullanılabilir kod parçaları oluşturmak için güçlü bir araçtır. React kullanarak daha karmaşık uygulamalar geliştirmek için, component yapısını daha derinlemesine öğrenmek ve pratik yapmak önemlidir.

Sınıf Bileşenler (Class Components) ve Fonksiyonel Bileşenler(Functional Components) hakkında herkesin aklına takılacak soru işaretlerini cevaplandıralım!

React uygulamaları geliştirirken iki temel bileşen yapısıyla karşılaşırız: sınıf bileşenleri (class components) ve fonksiyonel bileşenler (functional components). Her iki yapının da avantajları ve dezavantajları vardır.

Sınıf Bileşenleri (Class Components)

Avantajlar:

  • Sınıf bileşenleri, this.state özelliğini kullanarak durumu yönetir. Bu, bileşenin kendi iç durumunu tutmasına ve güncellemesine olanak tanır.
  • Sınıf bileşenleri, hata ayıklama sürecini kolaylaştıran daha kapsamlı hata mesajları sağlayabilir.
  • componentDidMount, componentDidUpdate, componentWillUnmount gibi yaşam döngüsü metodları, sınıf bileşenlerinde kullanılabilir. Bu metodlar, bileşenin farklı aşamalarında kodun çalışmasını sağlar.

componentDidMount():

  • componentDidMount, bileşenin DOM'a yerleştirildiği (mount edildiği) anda çağrılır.
  • Bu metod, bir bileşenin başlangıç durumu oluşturulduktan ve DOM’a eklenildikten sonra çalışan kodları içerir.
  • Genellikle, veri yükleme, abonelik başlatma veya diğer başlangıç ayarları için kullanılır.

componentDidUpdate(prevProps, prevState):

  • componentDidUpdate, bileşen güncellendiğinde çağrılır.
  • Bu metod, bir bileşenin güncelleme sonrası yeni prop’ları veya durumu aldıktan sonra çalışan kodları içerir.
  • Önceki props ve durum, prevProps ve prevState parametreleri aracılığıyla erişilebilir.
  • Genellikle, bileşenin durumu değiştiğinde state’e bağlı olarak yeni verileri getirme veya güncelleme işlemleri için kullanılır.

componentWillUnmount():

  • componentWillUnmount, bir bileşenin DOM'dan kaldırıldığı (unmount edildiği) anda çağrılır.
  • Bu metod, bir bileşenin artık kullanılmayacağı ve temizlenmesi gerektiği zaman çalışan kodları içerir.
  • Genellikle, abonelikleri iptal etme, zamanlayıcıları temizleme veya diğer temizleme işlemleri için kullanılır.

Bu yaşam döngüsü yöntemleri, React sınıf bileşenlerinin farklı aşamalarında kodun çalışmasını sağlar ve bileşenin davranışını kontrol etmek için önemlidir. Ancak, React 16.8 ve sonraki sürümlerde, fonksiyonel bileşenlerde Hooks kullanılarak bu yaşam döngüsü metodlarının yerini alabilirsiniz. Örneğin, useEffect hook'u, componentDidMount, componentDidUpdate ve componentWillUnmount'un yerine geçer.

import React, { Component } from 'react';

class ExampleComponent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

// componentDidMount kullanımı
componentDidMount() {
console.log('Component did mount');
// Bileşen ilk kez DOM'a yerleştirildiğinde çalışacak kodlar buraya yazılır
// Genellikle veri yükleme veya başlangıç ayarları için kullanılır
}

// componentDidUpdate kullanımı
componentDidUpdate(prevProps, prevState) {
console.log('Component did update');
// Bileşen güncellendiğinde çalışacak kodlar buraya yazılır
// Önceki ve yeni props/durumları karşılaştırarak özel işlemler gerçekleştirilebilir
}

// componentWillUnmount kullanımı
componentWillUnmount() {
console.log('Component will unmount');
// Bileşen DOM'dan kaldırılmadan önce çalışacak kodlar buraya yazılır
// Genellikle abonelikleri iptal etme veya temizlik işlemleri için kullanılır
}

render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increase Count
</button>
</div>
);
}
}

export default ExampleComponent;

Dezavantajlar:

  • Sınıf bileşenleri genellikle daha karmaşıktır ve daha fazla kod yazmayı gerektirir. Özellikle büyük projelerde, sınıf bileşenleri yönetilebilirlik açısından zor olabilir.
  • this bağlamı problemi sınıf bileşenlerinde sıkça karşılaşılan bir sorundur. Bu, fonksiyonları doğru bağlamda çalıştırmak için ekstra çaba gerektirebilir.
import React, { Component } from 'react';

class ClassComponent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}

incrementCount() {
this.setState({ count: this.state.count + 1 });
}

render() {
return (
<div>
<h2>Sınıf Bileşeni</h2>
<p>Count: {this.state.count}</p>
<button onClick={this.incrementCount}>Artır</button>
</div>
);
}
}

export default ClassComponent;

Functional Components ( Fonksiyonel Bileşenler )

Avantajları

  • Fonksiyonel bileşenler daha az sözdizimi kullanır ve genellikle daha okunaklıdır. Bu, bileşenin kodunu daha hızlı anlamayı ve yönetmeyi sağlar.
  • Fonksiyonel bileşenler, sınıf bileşenlerine kıyasla daha hızlı çalışabilir. Çünkü fonksiyonel bileşenlerin oluşturulması ve yürütülmesi daha az maliyetlidir.
  • Fonksiyonel bileşenler, React 16.8 ile birlikte gelen hooks’u kullanarak durumu ve diğer özellikleri yönetebilir. Bu, sınıf bileşenlerine benzer bir işlevsellik sağlar ancak daha temiz bir sözdizimi sunar.

Dezavantajları

  • Hooks’lar olmadan, fonksiyonel bileşenler durumu yönetemez. Bu nedenle, hooks kullanmadan önce durum yönetimi biraz zahmetli olabilir.
  • Yaşam döngüsü metodları doğrudan kullanılamaz. Bunun yerine, useEffect hook'u kullanılır, ancak bu bazen karmaşıklığa neden olabilir.
  • Eski tarayıcılarda veya React öncesi projelerde, fonksiyonel bileşenlerin kullanımı kısıtlanabilir.
import React, { useState } from 'react';

const FunctionalComponent = () => {
const [count, setCount] = useState(0);

const incrementCount = () => {
setCount(count + 1);
};

return (
<div>
<h2>Fonksiyonel Bileşen</h2>
<p>Count: {count}</p>
<button onClick={incrementCount}>Artır</button>
</div>
);
};

export default FunctionalComponent;

JSX ve JavaScript (JS) Arasındaki Temel Farklar

Söz Dizimi (Syntax):

  • JSX: JSX, JavaScript ile XML benzeri bir söz dizimi sunar. HTML benzeri yapılar kullanılarak UI bileşenleri tanımlanabilir. JSX kodu, React tarafından JavaScript koduna dönüştürülür ve tarayıcıda çalıştırılmadan önce yorumlanır.
  • JavaScript: JavaScript, daha temel bir dil yapısına sahiptir. HTML benzeri yapılar yerine, DOM manipülasyonları ve element oluşturma işlemleri genellikle JavaScript kullanılarak yapılır.

Kod Okunabilirliği (Code Readability):

  • JSX: JSX, HTML benzeri yapısıyla kodun daha okunabilir olmasını sağlar. Componentler ve bunların ilişkili işlevlerini daha açık bir şekilde tanımlamak mümkündür.
  • JavaScript: JavaScript’te, DOM manipülasyonları ve HTML elementlerini oluşturma işlemleri genellikle daha karmaşık ve daha az okunabilir olabilir.

Performans (Performance):

  • JSX: JSX, React tarafından optimize edilerek JavaScript koduna dönüştürülür. Bu sayede, tarayıcı tarafından daha hızlı bir şekilde işlenebilir.
  • JavaScript: Temel JavaScript kullanımıyla oluşturulan DOM manipülasyonları, bazı durumlarda daha düşük performansa neden olabilir.
import React from 'react';

const ButtonJS = () => {
return (
React.createElement('button', null, 'JS Button')
);
}

export default ButtonJS;
import React from 'react';

const Button = () => {
return (
<button>
JSX Button
</button>
);
}

export default Button;
import React from 'react';
import Button from './Button';
import ButtonJS from './ButtonJS';

const App = () => {
return (
<div>
<h1>Button Componentlerinin Kullanımı</h1>
<Button />
<ButtonJS />
</div>
);
}

export default App;

Yukarıdaki kod örneklerine de bakacak olursak JSX’in JavaScript’e göre avantajlarından biri, kodun daha okunabilir olması ve bileşenleri tanımlamanın daha kolay olmasıdır. JSX, HTML benzeri bir söz dizimi kullanarak UI bileşenlerini tanımlar, bu da kodun daha yapılandırılmış ve anlaşılır olmasını sağlar. Ayrıca, JSX kullanarak bileşenleri bir araya getirmek ve ilişkilendirmek daha doğal bir his verir, çünkü JSX, HTML benzeri yapıları kullanarak bileşenleri birbirine bağlar. Bu, geliştiricilerin kodu daha hızlı ve daha etkili bir şekilde yazmasına olanak tanırken, aynı zamanda bakımını ve geliştirmesini de kolaylaştırır. Bu nedenle, JSX, karmaşık UI’lerin oluşturulması ve yönetilmesi için JavaScript’e göre daha uygun bir seçenek olabilir.

Props Kavramı ve Kullanımı

Props, React’in bel kemiği konularından biridir ve önemlidir çünkü komponentler arasında veri taşımamıza olanak sağlar. Props’u doğru kullanmak, React uygulamalarınızı daha modüler ve esnek hale getirebilir.

Öncelikle, bir komponente veri taşımak için props kullanırız. Örneğin, bir ürün listesi oluştururken her bir ürünü farklı bir komponent olarak gösterebiliriz. Bu komponentlere ürün adı, fiyatı gibi özellikleri props olarak geçiririz. Böylece, her bir ürün komponenti kendi verilerini alır ve gösterir.

Props’u kullanmak için öncelikle bir komponenti çağırırken props adını verdiğimiz bir nesne geçiririz. Bu nesne içinde taşımak istediğimiz veriler bulunur. Ardından, bu verileri çağrılan komponentin içinde props olarak yakalarız ve kullanırız.

Örneğin, bir ürün listesi oluştururken her bir ürünü props olarak geçiririz ve bu ürünlerin adını ve fiyatını gösteririz. Ayrıca, komponent içinde başka bir komponenti çağırırken, bu çağrılan komponente de aynı props’u geçiririz, böylece veri akışını sağlarız.

import React, { useState } from 'react';

function ProductList(props) {
return (
<div>
<h1>Product List</h1>
<ul>
{props.products.map((product) => (
<li key={product.id}>
{product.name} - {product.price} $
</li>
))}
</ul>
</div>
);
}

export default ProductList;
import './App.css'
import ProductList from './components/PropsProductExample';

function App() {
const products = [
{ id: 1, name: 'Computer', price: 5000 },
{ id: 2, name: 'Phone', price: 3000 },
{ id: 3, name: 'Tablet', price: 2000 },
];

return <ProductList products={products} />;
}

export default App

Props’un dışında, bir komponent içinde başka bir komponenti₺li tanımlamanın da mümkün olduğunu belirtmek isterim. Bu yöntemle, bir komponent içinde daha karmaşık yapılar oluşturabiliriz. Ancak, bu yöntemi kullanırken dikkat etmemiz gereken şey, iç içe geçen komponentler arasında veri akışını doğru bir şekilde sağlamaktır. Props konusunu doğru bir şekilde anlamak ve kullanmak, React uygulamalarınızı daha etkili ve modüler hale getirebilir. Bol bol pratik yaparak, bu konuyu daha iyi kavrayabilir ve React projelerinizde daha verimli bir şekilde kullanabilirsiniz.

React Hooks Yapısı

React Hooks, React 16.8 sürümüyle birlikte tanıtılan ve fonksiyonel componentlerde state ve diğer React özelliklerini kullanmamızı sağlayan bir özelliktir.React Hooks, React uygulamalarında fonksiyonel componentlerde state ve diğer React özelliklerini kullanmamızı sağlayan bir özelliktir. useState hook'u ile state yönetimi, useEffect hook'u ile yaşam döngüsü işlemleri ve useContext hook'u ile context kullanımı gibi işlemler gerçekleştirilebilir. Hooks, kodun daha okunabilir, yönetilebilir ve yeniden kullanılabilir olmasını sağlar, aynı zamanda componentler arasında state ve fonksiyonların daha kolay paylaşılmasını sağlar. Bu sayede, React Hooks, React uygulamalarının geliştirilmesini daha verimli hale getirir.

useState Kullanımı

useState, React'ta yerleşik bir hook'tur ve bileşenlerde state yönetmek için kullanılır. State, bileşenin durumu veya verileri sakladığı yerdir ve bileşenin render edildiğinde bu verilere erişmesini sağlar. useState, fonksiyon bileşenlerinde state kullanmamızı sağlar.

import React, { useState } from 'react';

function UseStateExample1() {
const [count, setCount] = useState(0);

return (
<div>
<p>You clicked {count} times</p>
{/* Butona tıklandığında setCount fonksiyonunu çağırarak count state'ini güncelliyoruz */}
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

export default UseStateExample1;

Yukarıdaki örnekte, useState hook'u ile bir state değişkeni olan count ve bu değişkeni güncellemek için bir fonksiyon olan setCount tanımlanmıştır. useState içine verilen parametre, state'in başlangıç değeridir (yukarıdaki örnekte 0). Bu değişkenler, bileşenin içinde kullanılarak state değerlerini okumak veya güncellemek için kullanılır.

Butona tıklandığında, setCount fonksiyonu kullanılarak count state'i güncellenir. setCount fonksiyonu, mevcut state değerini parametre olarak alır ve yeni state değerini belirlemek için bu parametreyi kullanır. Yukarıdaki örnekte, her tıklamada count değeri bir artar.

Bu şekilde, useState hook'u kullanarak React bileşenlerinde state yönetebilir ve bu state'i güncelleyebiliriz.

import React, { useState } from 'react';

function UseStateExample2() {
// Bir obje olarak state tanımlıyoruz
const [user, setUser] = useState({ name: '', age: 0 });

return (
<div>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
<input
type="text"
placeholder="Name"
value={user.name}
onChange={(e) => setUser({ ...user, name: e.target.value })}
/>
<input
type="number"
placeholder="Age"
value={user.age}
onChange={(e) => setUser({ ...user, age: parseInt(e.target.value) || 0 })}
/>
</div>
);
}

export default UseStateExample2;

Yukarıdaki örnekte, useState hook'u kullanılarak bir obje olan user state'i tanımlanmıştır. Bu obje içinde kullanıcı adını (name) ve yaşını (age) tutuyoruz.

Input alanlarına girilen değerleri kullanarak user state'ini güncellemek için onChange olayı kullanılır. Her input alanı için onChange olayı tetiklendiğinde, önceki state değerinin bir kopyası alınır ve sadece değişen alan güncellenir.

Örneğin, kullanıcı adı input alanına bir değer girildiğinde, setUser fonksiyonu çağrılarak user objesinin name alanı güncellenir. Yaş input alanına bir değer girildiğinde de benzer bir şekilde user objesinin age alanı güncellenir. Bu sayede, user state'ini güncellemek için mevcut state değerini değiştirmeden, sadece değişen alanı güncellemiş oluruz.

...user ifadesi, mevcut user objesinin tüm alanlarını kopyalamak için kullanılır. Sonra bu kopya üzerinde age alanı güncellenir.

import React, { useState } from 'react';

function UseStateExample3(){
// names adında bir dizi tanımlıyoruz
const [names, setNames] = useState(["kardel", "ruveyda", "cetin"]);

return (
<div>
<h2>İsimler</h2>
<ul>
{names.map((name, index) => (
<li key={index}>{name}</li>
))}
</ul>
</div>
);
};

export default UseStateExample3;

Bu örnekte, names adında bir dizi tanımlanmış ve içine "kardel", "ruveyda" ve "cetin" isimleri eklenmiştir. Daha sonra bu isimler, bir <ul> listesinde map fonksiyonuyla döngüye alınarak ekrana yazdırılır.

useEffect Kullanımı

React uygulamalarında, belirli aksiyonlar alındığında veya bileşenin belirli yaşam döngüsü aşamalarında işlem yapmak oldukça yaygındır. Örneğin, bir sayfa yüklendiğinde API’den veri çekmek veya bir State’in değeri değiştiğinde bazı güncellemeler yapmak gerekebilir. İşte tam da bu noktada, useEffect hook’u devreye girer. useEffect hook’u içinde istenen callback fonksiyonu, belirli bir yan etkiyi gerçekleştirmek için kullanılır. Bu yan etki, bileşenin render edilmesinden sonra ortaya çıkabilir ve API çağrıları yapma, abonelik oluşturma, DOM manipülasyonları gibi işlemleri içerebilir. useEffect hook’u, bir bileşenin render edilmesinden sonra belirli bir işlemi gerçekleştirmek için kullanılır. Örneğin, bir bileşen yüklendiğinde bir API’den veri almak veya belirli bir State değeri değiştiğinde bazı güncellemeler yapmak isteyebiliriz. useEffect, bu tür senaryolarda kullanılmak üzere tasarlanmıştır.

import React, { useState, useEffect } from 'react';

function UseEffectExample1() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');

useEffect(() => {
console.log('Her zaman çalışır');
});

return (
<div>
<p>First Name: {firstName}</p>
<p>Last Name: {lastName}</p>
<button onClick={() => setFirstName('John')}>Change First Name</button>
<button onClick={() => setLastName('Doe')}>Change Last Name</button>
</div>
);
}

export default UseEffectExample1;

Yukarıdaki örnekte, useEffect hook’u kullanarak bileşenin her render edilmesinden sonra bir log mesajı yazdırılır. useEffect hook’unun içindeki callback fonksiyonunun herhangi bir bağımlılık belirtilmediğinden dolayı, her render işlemi gerçekleştiğinde çalışacaktır. Yani, bileşenin her yeniden render edilişinde useEffect de çalışacaktır. Bu durum, bileşenin state değişikliklerinden bağımsız olarak, bileşenin her aksiyonundan sonra useEffect’in çalıştığını gösterir. Özellikle useEffect içinde bir servis çağrısı veya veritabanı sorgusu gibi asenkron işlemler yapılıyorsa, her bileşen yeniden render edildiğinde useEffect yeniden çalışacak ve bu işlemler tekrar gerçekleştirilecektir. Bu durum, uygulamanın performansını etkileyebilir, çünkü gereksiz yere tekrar tekrar servis çağrıları yapılabilir veya veritabanı sorguları gerçekleştirilebilir. Bu nedenle, useEffect içinde bu tür asenkron işlemler yapılıyorsa, bağımlılıkları dikkatlice belirlemek ve gereksiz yeniden render işlemlerini engellemek önemlidir.

import React, { useState, useEffect } from 'react';

function UseEffectExample2() {
const [counter, setCounter] = useState(0);

useEffect(() => {
// Bu kısım sadece bileşen ilk kez render edildiğinde çalışır
console.log('İlk kez render edildiğinde çalışır.');
}, []); // Boş dizi, useEffect'in sadece bir kere çalışmasını sağlar

return (
<div>
Use Effect Example
</div>
);
}

export default UseEffectExample2;

Yukarıdaki kod örneğinde, useEffect hook’u içinde boş bir dizi verilerek, callback fonksiyonunun sadece bileşenin ilk kez render edilmesinden sonra çalışması sağlanır. Bu sayede, useEffect içindeki kod sadece bir kere çalışır.

import React, { useState, useEffect } from 'react';

function UseEffectExample3() {
const [name, setName] = useState('');
const [surname, setSurname] = useState('');

useEffect(() => {
// Bu kısım sadece bileşen ilk kez render edildiğinde ve name değeri değiştiğinde çalışır
console.log('Bu kısım sadece bileşen ilk kez render edildiğinde ve name değeri değiştiğinde çalışır');
}, [name]); // name değiştiğinde useEffect yeniden çalışır

return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
type="text"
value={surname}
onChange={(e) => setSurname(e.target.value)}
placeholder="Surname"
/>
</div>
);
}

export default UseEffectExample3;

Yukarıdaki örnekte, useEffect hook’u içinde ikinci parametre olarak [name] dizisi verilerek, useEffect'in sadece name state'i değiştiğinde çalışması sağlanır. Bu, name state'i değiştiğinde useEffect'in tekrar render edileceği anlamına gelir. Dolayısıyla, bileşen ilk kez render edildiğinde ve name değeri değiştiğinde useEffect çalışır.

Demo Projeler

React.js 101 eğitimi sonunda sizlere iki adet demo projesi oluşturacağım. İlk demo uygulamamızı oluştururken, axios kütüphanesini kullanıp anlayabilmemizi sağlayan bir demo projesi gerçekleştireceğiz, ikinci demo projemizde ise Pomodoro tekniğinin temel prensiplerine dayanacak ve kullanıcıların çalışma sürelerini ve mola aralarını kolayca yönetmelerini sağlayacak bir başlangıç aracı geliştireceğiz. Uygulama geliştirme sürecinde React.js’in temel kavramlarını öğrenirken, aynı zamanda pratik yapma fırsatı bulacağız. Demo uygulamamızı oluştururken adım adım ilerleyeceğiz ve sonunda kendi kişisel Pomodoro uygulamanızı geliştirmenin keyfini çıkaracaksınız. Hazırsanız, React.js ile Pomodoro uygulaması oluşturma yolculuğumuza başlayalım!

Proje 1 : Axios Project

Öncelikle API Nedir?

API, Application Programming Interface’in kısaltmasıdır ve yazılım uygulamaları arasında iletişim kurmayı sağlayan bir arayüzdür. Bir uygulama, bir API aracılığıyla diğer bir uygulamaya istek gönderir ve isteğe bağlı olarak bir yanıt alır.

REST API, Representational State Transfer’in kısaltmasıdır ve internet üzerinden kaynaklara (örneğin, verilere veya işlemlere) erişmek için kullanılan bir mimari tarzdır. RESTful API’lar genellikle HTTP protokolü üzerinden iletişim kurarlar ve JSON veya XML gibi veri formatlarını kullanarak bilgi alışverişi yaparlar.

SOAP API, Simple Object Access Protocol’un kısaltmasıdır ve ağ üzerinden yapılandırılmış bilgilere erişmek için kullanılan bir protokoldür. SOAP API’lar genellikle XML tabanlı mesajları kullanır ve WSDL (Web Services Description Language) dosyaları aracılığıyla tanımlanır.

HTTP protokolü, web tarayıcıları ve sunucular arasında iletişim kurmak için kullanılan bir iletişim protokolüdür. HTTP, istemci-sunucu modeline dayalıdır ve istemciler (genellikle web tarayıcıları) sunuculara (web siteleri veya web uygulamaları) istek gönderir ve sunucular da istemcilere yanıt verir.

React’ten APIlere istek göndermek için 3 tane yöntem var ;

  • XMLHttpRequest
  • Fetch
  • Axios

XML HTTP Request, JavaScript tarafından sunulan bir API’dır ve web tarayıcıları üzerinde HTTP istekleri göndermek ve almak için kullanılır. Ancak, XML HTTP Request kullanımı eski ve karmaşıktır ve yerine fetch API veya Axios gibi modern çözümler tercih edilir.

Fetch API, web tarayıcılarında sunulan bir API’dir ve HTTP istekleri göndermek ve almak için kullanılır. Fetch API, Promise tabanlıdır ve modern JavaScript tarafından kolayca kullanılabilir.

Axios, Node.js ve web tarayıcılarında kullanılabilen bir HTTP istemci kütüphanesidir. Axios, Promise tabanlıdır ve basit ve kullanıcı dostu bir API sağlar.

Hazır servislerden yararlanma : Json-Server

JSON Server, bir tür REST servisidir ve genellikle eğitimlerde kullanılmak üzere hazırlanmıştır. Örneğin, JSON Placeholder gibi birçok hizmet bulunmaktadır. JSON Placeholder, bir grup REST servisini barındıran bir sunucu uygulamasıdır ve genellikle eğitimlerde kullanılır. Buradaki servisler, önceden yazılmış ve kullanıma hazır olduğu için, geliştirme sürecini hızlandırır.

Bizler eğitim için proje geliştirirken, genellikle bu tür hazır servisleri kullanırız. Örneğin, bir backend geliştiricisi olarak, JSON Server gibi bir servisi kullanarak frontend geliştiricimize “Bu servis üzerinden veri alabilirsin. Örneğin, /posts endpoint'ine GET isteği gönderdiğinde, tüm gönderileri alırsın. Ya da /posts/1 şeklinde bir istekte bulunduğunda, id'si 1 olan gönderiyi alırsın." şeklinde bilgi verebiliriz. Bu şekilde, birbirimize senkronize bir şekilde çalışıp, projeyi geliştirebiliriz.

npm install json-server

Yukarıdaki komutu kullanarak json-server’ı localinize kurabilirsiniz.

JSON Server kurulduktan sonra, bir JSON dosyası oluşturarak sahte verilerinizi tanımlamanız gerekecek. Örneğin, db.json adında bir dosya oluşturup içine sahte verilerinizi yazabilirsiniz.

{
"users": [
{
"id": "1",
"username": "user1"
},
{
"id": "2",
"username": "user2"
}
]
}

Son olarak, JSON Server’ı başlatmak için aşağıdaki komutu çalıştırın ve db.json dosyasının yolunu belirtin.

npx json-server --watch db.json 

Ve mutlu son..

http://localhost:3000/users

Projenin ApiService.jsx alanını yazalım

import axios from 'axios';

const baseURL = 'http://localhost:3000';

function Apiservice () {
// Tüm gönderileri getiren GET isteği
const getAllUsers = () => {
return axios.get(`${baseURL}/users`);
};

// Yeni gönderi ekleyen POST isteği
const addUser = (postData) => {
return axios.post(`${baseURL}/users`, postData);
};

// Belirli bir gönderiyi güncelleyen PUT isteği
const updateUser = (postId, putData) => {
return axios.put(`${baseURL}/users/${postId}`, putData);
};

// Belirli bir gönderiyi silen DELETE isteği
const deleteUser = (postId) => {
return axios.delete(`${baseURL}/users/${postId}`);
};

return {
getAllUsers,
addUser,
updateUser,
deleteUser
};
};

export default Apiservice;

Bu kod bir API servisini yönetmek için kullanılıyor. Kütüphane olarak axios kullanılmış. İşlevsel bileşen Apiservice içinde tanımlanmıştır.

  1. axios kütüphanesinden istek yapmak için bir baseURL belirlenmiş. Bu, API isteklerinin kök URL'sini temsil eder.
  2. Apiservice adında bir fonksiyon tanımlanmış. Bu, API isteklerini yönetmek için bir arayüz sağlar.
  3. getAllUsers: Tüm kullanıcıları getiren GET isteğini gerçekleştirir.
  4. addUser: Yeni bir kullanıcı eklemek için POST isteği gönderir.
  5. updateUser: Belirli bir kullanıcıyı güncellemek için PUT isteği gönderir.
  6. deleteUser: Belirli bir kullanıcıyı silmek için DELETE isteği gönderir.

Bu kodu çalıştırmak için axios kütüphanesini projenize eklemeniz gerekecek. Projeyi oluşturmak için npm veya yarn kullanabilirsiniz.

axios kütüphanesini eklemek için terminalde aşağıdaki komutu çalıştırabilirsiniz.

npm install axios

Bu komut, Axios kütüphanesini projenize ekler. Önceden belirttiğim gibi, ayrıca json-server'ı başlatmak için şu komutu kullanabilirsiniz:

npx json-server --watch db.json --port 3000

Bu, projenizin altındaki db.json dosyasını izleyerek bir JSON sunucusu başlatır ve http://localhost:3000 adresini kullanır.

Projenin App.jsx alanını yazalım

import React, { useState, useEffect } from 'react';
import ApiService from './api/ApiService';

const App = () => {
const [users, setUsers] = useState([]);
const [newUserData, setNewUserData] = useState({
username: ''
});
const [selectedUser, setSelectedUser] = useState(null);
const apiService = new ApiService();

useEffect(() => {
// Sayfa yüklendiğinde tüm kullanıcıları getir
apiService.getAllUsers()
.then(response => {
setUsers(response.data);
})
.catch(error => {
console.error('Error fetching users:', error);
});
}, []);

const handleInputChange = (e) => {
const { name, value } = e.target;
setNewUserData(prevData => ({
...prevData,
[name]: value,
}));
};

const handleAddUser = () => {
// Yeni kullanıcıyı oluştur
apiService.addUser(newUserData)
.then(response => {
setUsers(prevUsers => [...prevUsers, response.data]);
setNewUserData({
username: ''
});
})
.catch(error => {
console.error('Error adding user:', error);
});
};

const handleDeleteUser = (userId) => {
// Kullanıcıyı sil
apiService.deleteUser(userId)
.then(() => {
setUsers(prevUsers => prevUsers.filter(user => user.id !== userId));
})
.catch(error => {
console.error('Error deleting user:', error);
});
};

const handleEditUser = (user) => {
setSelectedUser(user);
setNewUserData({
username: user.username
});
};

const handleUpdateUser = () => {
// Kullanıcıyı güncelle
apiService.updateUser(selectedUser.id, newUserData)
.then(response => {
setUsers(prevUsers =>
prevUsers.map(user => (user.id === selectedUser.id ? response.data : user))
);
setSelectedUser(null);
setNewUserData({
username: ''
});
})
.catch(error => {
console.error('Error updating user:', error);
});
};


const handleKeyDown = (e) => {
if (e.key === 'Enter') {
if (selectedUser) {
handleUpdateUser();
} else {
handleAddUser();
}
}
};



return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>
<h2>{user.username}</h2>
<button onClick={() => handleEditUser(user)}>Edit</button>
<button onClick={() => handleDeleteUser(user.id)}>Delete</button>
</li>
))}
</ul>
{selectedUser && (
<>
<h2>Edit User</h2>
<input type="text" name="username" placeholder="Username" value={newUserData.username} onChange={handleInputChange} onKeyDown={handleKeyDown} />
<button onClick={handleUpdateUser}>Update User</button>
</>
)}
{!selectedUser && (
<>
<h2>Add New User</h2>
<input type="text" name="username" placeholder="Username" value={newUserData.username} onChange={handleInputChange} onKeyDown={handleKeyDown} />
<button onClick={handleAddUser}>Add User</button>
</>
)}
</div>
);
};

export default App;
  1. İlk olarak, react paketinden useState ve useEffect fonksiyonlarını ve kendi oluşturduğumuz ApiService bileşenini import ediyoruz.
  2. App isimli bir fonksiyonel bileşen oluşturuyoruz. Bu bileşen, uygulamanın ana bileşenidir.
  3. Bileşen içerisinde, kullanıcıların listesini ve yeni kullanıcı verisini saklamak için useState hook'unu kullanarak state'leri tanımlıyoruz. Ayrıca, seçili bir kullanıcıyı saklamak için selectedUser adında bir state daha tanımlıyoruz.
  4. ApiService bileşeninden bir örnek oluşturuyoruz. Bu örneği, API isteklerini yapmak için kullanacağız.
  5. useEffect hook'u kullanarak, bileşen yüklendiğinde bir defaya mahsus tüm kullanıcıları almak için bir API isteği gönderiyoruz. API'den gelen verileri setUsers fonksiyonu ile state'e ekliyoruz.
  6. Kullanıcı adı alanını değiştirmek için handleInputChange fonksiyonunu tanımlıyoruz. Bu fonksiyon, input alanına girilen veriyi alarak newUserData state'ini günceller.
  7. Yeni bir kullanıcı eklemek için handleAddUser fonksiyonunu tanımlıyoruz. Bu fonksiyon, apiService.addUser fonksiyonunu kullanarak yeni kullanıcıyı ekler ve ardından kullanıcı listesini günceller.
  8. Bir kullanıcıyı silmek için handleDeleteUser fonksiyonunu tanımlıyoruz. Bu fonksiyon, apiService.deleteUser fonksiyonunu kullanarak belirli bir kullanıcıyı siler ve kullanıcı listesini günceller.
  9. Bir kullanıcıyı düzenlemek için handleEditUser fonksiyonunu tanımlıyoruz. Bu fonksiyon, seçili kullanıcıyı selectedUser state'ine atar ve kullanıcı adını input alanına yerleştirir.
  10. Bir kullanıcıyı güncellemek için handleUpdateUser fonksiyonunu tanımlıyoruz. Bu fonksiyon, seçili kullanıcıyı günceller ve ardından kullanıcı listesini günceller.
  11. Kullanıcının klavyeden Enter tuşuna basmasını dinleyen handleKeyDown fonksiyonunu tanımlıyoruz. Eğer Enter'a basıldıysa ve bir kullanıcı seçiliyse, kullanıcıyı güncellemek için handleUpdateUser fonksiyonunu çağırır; aksi takdirde, yeni bir kullanıcı eklemek için handleAddUser fonksiyonunu çağırır.
  12. Son olarak, bileşenin render fonksiyonunda, kullanıcı listesini ekrana yazdırırız. Her kullanıcı için bir liste öğesi oluştururuz. Her öğede kullanıcı adını, bir “Edit” düğmesini ve bir “Delete” düğmesini görüntüleriz. Ayrıca, yeni bir kullanıcı eklemek veya mevcut bir kullanıcıyı güncellemek için bir form alanı ekleriz.

Proje 2: Pomodoro Project

Peki nedir bu Pomodoro?

Pomodoro tekniği, zamanı etkin bir şekilde yönetmeyi ve çalışma verimliliğini artırmayı hedefleyen bir yöntemdir. Bu teknik, belirli zaman dilimlerinde yoğun çalışma periyotları ile kısa dinlenme aralarının sıralandığı bir döngüyü içerir. Örneğin, 25 dakikalık bir çalışma süresi (Pomodoro) ardından 5 dakikalık bir mola süresi gibi belirlenen zaman dilimleri kullanılır.

Pomodoro uygulamaları, kullanıcıların bu zaman dilimlerini takip etmelerine ve çalışma seanslarını düzenlemelerine yardımcı olur. Kullanıcılar genellikle belirli bir görev veya projeye odaklanmak için bir Pomodoro başlatır ve çalışma süresi boyunca dikkatlerini dağıtacak her türlü etkenden kaçınırlar. Ardından, çalışma süresi tamamlandığında, kısa bir mola vererek dinlenirler.

Bu döngü, hem odaklanma süresini artırarak verimliliği artırır hem de uzun süreli çalışma sürelerinin yarattığı yorgunluğu azaltır. Pomodoro uygulamaları genellikle kullanıcılara çalışma sürelerini, molaları ve toplamda tamamlanan Pomodoro sayısını takip etme imkanı sunar. Bu sayede kullanıcılar çalışma alışkanlıklarını daha iyi anlarlar ve zamanlarını daha verimli bir şekilde yönetebilirler.

TimerComponent.jsx Yazılması

import React, { useState, useEffect } from 'react';
import moment from 'moment';

function TimerComponent () {
const [time, setTime] = useState(25 * 60); // Saniye cinsinden süre
const [isActive, setIsActive] = useState(false);

useEffect(() => {
let intervalId;

if (isActive) {
intervalId = setInterval(() => {
if (time <= 0) {
clearInterval(intervalId);
setIsActive(false);
playDefaultNotificationSound();
} else {
setTime((prevTime) => prevTime - 1);
}
}, 1000);
}

return () => clearInterval(intervalId);
}, [isActive, time]);

const startTimer = () => {
setIsActive(true);
};

const resetTimer = () => {
setIsActive(false);
setTime(25 * 60); // Saniye cinsinden 25 dakika
};

const playDefaultNotificationSound = () => {
try {
const audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
oscillator.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.5);
} catch (error) {
console.error('Varsayılan ses çalınırken bir hata oluştu:', error);
}
};

const formattedTime = moment.utc(time * 1000).format('mm:ss');

return (
<div>
<h2>{formattedTime}</h2>
<button className="timer-button" onClick={startTimer}>
Başlat
</button>
<button className="timer-button" onClick={resetTimer}>
Sıfırla
</button>
</div>
);
};

export default TimerComponent;

React ve Gerekli Kütüphanelerin İçeri Aktarımı

import React, { useState, useEffect } from 'react';
import moment from 'moment';

Bu kod bloğu, React ve useState, useEffect gibi React hooks'larını ve moment adlı bir zaman işleme kütüphanesini içeri aktarır. Bu kütüphane, zamanı biçimlendirmek için kullanılacak.

TimerComponent Fonksiyonu

Burada fonksiyonel bir komponent kullanımı gerçekleşmiştir.

function TimerComponent() {

State Tanımlama

const [time, setTime] = useState(25 * 60); // Saniye cinsinden süre
const [isActive, setIsActive] = useState(false);

useState hook'u kullanılarak, time ve isActive adında iki durum (state) tanımlanır. time, saniye cinsinden süreyi, isActive ise zamanlayıcının aktif olup olmadığını belirten bir bayrak değerini tutar.

useEffect Hook’u

useEffect(() => {
let intervalId;

if (isActive) {
intervalId = setInterval(() => {
if (time <= 0) {
clearInterval(intervalId);
setIsActive(false);
playDefaultNotificationSound();
} else {
setTime((prevTime) => prevTime - 1);
}
}, 1000);
}

return () => clearInterval(intervalId);
}, [isActive, time]);

Bu kod parçası, bir interval (aralıklı) işlevini kullanarak zamanlayıcıyı başlatır. İlk olarak, setInterval fonksiyonu her saniyede bir çalışacak olan bir fonksiyonu alır. Bu fonksiyon, kalan zamanı azaltır ve zamanlayıcının süresinin bitip bitmediğini kontrol eder.

if (time <= 0): Eğer kalan süre sıfırdan küçük veya eşitse, yani zamanlayıcı tamamlandıysa:

  • clearInterval(intervalId): Interval'i temizler, böylece zamanlayıcıyı durdurur. setIsActive(false): isActive durumunu false olarak ayarlar, böylece zamanlayıcıyı durduğumuzu belirtir.
  • playDefaultNotificationSound(): Bildirim sesini çalar, kullanıcıyı zamanlayıcının sonlandığını bildirir.

Aksi takdirde:

  • setTime((prevTime) => prevTime - 1): setTime fonksiyonu kullanılarak, kalan süreyi bir saniye azaltır. prevTime önceki süreyi temsil eder. Bu, her saniye çağrıldığında kalan süreyi bir saniye azaltır ve zamanlayıcıyı günceller.

Bu kod parçası, zamanlayıcının her saniye azaltılarak ve tamamlandığında bildirim sesi çalarak nasıl çalışacağını tanımlar.

Zamanlayıcıyı Başlatma ve Sıfırlama Fonksiyonları

const startTimer = () => {
setIsActive(true);
};

const resetTimer = () => {
setIsActive(false);
setTime(25 * 60); // Saniye cinsinden 25 dakika
};

startTimer fonksiyonu, zamanlayıcıyı başlatmak için isActive durumunu true yapar. resetTimer fonksiyonu ise zamanlayıcıyı sıfırlar ve başlangıç süresini 25 dakikaya ayarlar.

Bildirim Sesi Çalma Fonksiyonu

playDefaultNotificationSound fonksiyonu, tarayıcıda bir bildirim sesi çalmak için AudioContext API'sini kullanır. Hata durumlarını kontrol eder ve konsola bir hata mesajı yazdırır.

const playDefaultNotificationSound = () => {
try {
const audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
oscillator.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.5);
} catch (error) {
console.error('Varsayılan ses çalınırken bir hata oluştu:', error);
}
};
  1. const audioContext = new (window.AudioContext || window.webkitAudioContext)();: İlk olarak, AudioContext API'sini kullanarak bir ses bağlamı oluşturulur. Bu API, tarayıcıda ses oluşturmak ve işlemek için kullanılır. window.AudioContext ve window.webkitAudioContext, farklı tarayıcıların farklı versiyonlarına destek sağlar. Bu nedenle, || (veya) operatörü kullanılarak tarayıcıya uygun olan sürüm seçilir.
  2. const oscillator = audioContext.createOscillator();: Ardından, audioContext.createOscillator() yöntemi kullanılarak bir osilatör oluşturulur. Osilatör, bir ses dalgası üretmek için kullanılır.
  3. oscillator.connect(audioContext.destination);: Oluşturulan osilatör, ses bağlamının çıkışına (audioContext.destination) bağlanır. Bu, osilatörün sesi nereden çalacağını belirtir. Burada, ses doğrudan kullanıcının cihazından çalınır.
  4. oscillator.start();: Osilatör başlatılır ve ses çalmaya başlar.
  5. oscillator.stop(audioContext.currentTime + 0.5);: Belirli bir süre sonra osilatör durdurulur. audioContext.currentTime anlık zamanı verir ve + 0.5 ile 0.5 saniye sonra osilatör durdurulur. Bu, kullanıcıya kısa bir bildirim sesi çalınmasını sağlar.

Eğer herhangi bir hata oluşursa, catch bloğu çalışır ve konsola bir hata mesajı yazılır. Bu, tarayıcı ses bağlamı veya osilatör oluşturma işleminde bir hata olduğunda kullanıcının bilgilendirilmesini sağlar.

Formatlanmış Zamanı Alma

formattedTime, saniye cinsinden zamanı mm:ss biçiminde biçimlendirir.

const formattedTime = moment.utc(time * 1000).format('mm:ss');

Bileşenin Dönüşü

return (
<div>
<h2>{formattedTime}</h2>
<button className="timer-button" onClick={startTimer}>
Başlat
</button>
<button className="timer-button" onClick={resetTimer}>
Sıfırla
</button>
</div>
);

Bileşenin dönüşünde, biçimlendirilmiş zamanı ve başlat/sıfırla düğmelerini içeren bir div bileşeni bulunur.

NoteComponent.jsx Yazılması

import React, { useState } from 'react';
import { FaCheck, FaTrash } from 'react-icons/fa';

function NoteComponent (){
const [note, setNote] = useState('');
const [notes, setNotes] = useState([]);

const handleNoteChange = (event) => {
setNote(event.target.value);
};

const addNote = () => {
if (note.trim() !== '') {
setNotes([...notes, { content: note, completed: false }]);
setNote('');
}
};

const handleKeyDown = (event) => {
if (event.key === 'Enter') {
addNote();
}
};

const toggleNote = (index) => {
const updatedNotes = [...notes];
updatedNotes[index].completed = !updatedNotes[index].completed;
setNotes(updatedNotes);
};

const deleteNote = (index) => {
const updatedNotes = [...notes];
updatedNotes.splice(index, 1);
setNotes(updatedNotes);
};

return (
<div className="note-section">
<h3>Notlar</h3>
<input
className="note-input"
type="text"
value={note}
onChange={handleNoteChange}
onKeyDown={handleKeyDown}
/>
<button className="note-button" onClick={addNote}>
Ekle
</button>
<ul className="note-list">
{notes.map((note, index) => (
<li key={index} className={note.completed ? 'completed' : ''}>
{note.content}
<button className="note-toggle" onClick={() => toggleNote(index)}>
{note.completed ? (
<FaCheck />
) : (
<FaCheck style={{ color: 'green' }} />
)}
</button>
<button className="note-delete" onClick={() => deleteNote(index)}>
<FaTrash />
</button>
</li>
))}
</ul>
</div>
);
};

export default NoteComponent;

State Tanımlamaları

const [note, setNote] = useState('');
const [notes, setNotes] = useState([]);
  • note: Kullanıcının girdiği notun değerini saklamak için bir state.
  • notes: Tüm notları tutan bir dizi state.

handleNoteChange Fonksiyonu

const handleNoteChange = (event) => {
setNote(event.target.value);
};
  • Kullanıcının not girişini takip eden bir fonksiyon. event.target.value kullanıcının girdiği metni içerir ve bu metin setNote ile note state'ine atanır.

addNote Fonksiyonu

const addNote = () => {
if (note.trim() !== '') {
setNotes([...notes, { content: note, completed: false }]);
setNote('');
}
};
  • Eğer kullanıcı boş bir not eklemeye çalışmıyorsa, yeni bir not ekler.
  • setNotes([...notes, { content: note, completed: false }]): Mevcut notlar dizisinin bir kopyasını alır ve içine yeni notu ekler. Bu yeni not, kullanıcının girdiği metni (note) ve başlangıçta tamamlanmamış (completed: false) bir durumu içerir.
  • setNote(''): Not eklendikten sonra, note state'i temizlenir.

handleKeyDown Fonksiyonu

const handleKeyDown = (event) => {
if (event.key === 'Enter') {
addNote();
}
};

Kullanıcı ‘Enter’ tuşuna bastığında çalışan bir fonksiyondur. Bu, kullanıcının hızlıca not eklemesine olanak tanır.

toggleNote, deleteNote Fonksiyonları

const toggleNote = (index) => {
const updatedNotes = [...notes];
updatedNotes[index].completed = !updatedNotes[index].completed;
setNotes(updatedNotes);
};
  • toggleNote fonksiyonu, belirli bir notun tamamlanma durumunu (true veya false) değiştirir.
  • İlk olarak, notes dizisinin bir kopyasını oluşturarak değişikliklerin orijinal diziyi etkilememesini sağlar.
  • Sonra, belirli bir index’teki notun completed özelliğini tersine çevirir (true ise false, false ise true yapar).
  • Son olarak, güncellenmiş notlar dizisini setNotes ile ayarlar, böylece arayüz güncellenir.
const deleteNote = (index) => {
const updatedNotes = [...notes];
updatedNotes.splice(index, 1);
setNotes(updatedNotes);
};
  • deleteNote fonksiyonu, belirli bir notu diziden kaldırır.
  • Yine, önce notes dizisinin bir kopyasını oluşturur.
  • Ardından, splice yöntemiyle belirtilen index'teki notu diziden çıkarır.
  • Son olarak, güncellenmiş notlar dizisini setNotes ile ayarlar, böylece arayüz güncellenir.

Her iki fonksiyon da, notlar dizisindeki değişikliklerin doğrudan orijinal diziye uygulanmasını önlemek için kopyalama yöntemini kullanır. Bu, React’ta state’in doğru bir şekilde güncellenmesini ve bileşenin yeniden render edilmesini sağlar.

Render (Return) Kısmı

return (
<div className="note-section">
<h3>Notlar</h3>
<input
className="note-input"
type="text"
value={note}
onChange={handleNoteChange}
onKeyDown={handleKeyDown}
/>
<button className="note-button" onClick={addNote}>
Ekle
</button>
<ul className="note-list">
{notes.map((note, index) => (
<li key={index} className={note.completed ? 'completed' : ''}>
{note.content}
<button className="note-toggle" onClick={() => toggleNote(index)}>
{note.completed ? (
<FaCheck />
) : (
<FaCheck style={{ color: 'green' }} />
)}
</button>
<button className="note-delete" onClick={() => deleteNote(index)}>
<FaTrash />
</button>
</li>
))}
</ul>
</div>
);
  • Kullanıcıya not eklemek, notları görmek ve düzenlemek için arayüzü içerir. Kullanıcının girdiği notlar notes dizisinden alınır ve haritalama yöntemiyle ekranda listelenir.

Bu adımlar, basit bir not uygulamasının temel özelliklerini açıklar. Kullanıcılar not ekleyebilir, notları tamamlayabilir veya silebilir.

Komponentlerin App.jsx’de Kullanılması

import React from 'react';
import './App.css';
import TimerComponent from '../src/components/TimerComponent';
import NoteComponent from '../src/components/NoteComponent';

const App = () => {
return (
<div className="App">
<h1>Pomodoro Timer</h1>
<TimerComponent />
<NoteComponent />
</div>
);
};

export default App;
  • App adında bir fonksiyonel bileşen tanımlanır.
  • Bu bileşen, <div> elementi içine yerleştirilmiştir ve App CSS sınıfı ile tanımlanmıştır.
  • Başlık olarak <h1> etiketi kullanılarak "Pomodoro Timer" metni gösterilir.
  • TimerComponent ve NoteComponent bileşenleri, <TimerComponent /> ve <NoteComponent /> olarak çağrılarak uygulamaya eklenir. Bu, bu bileşenlerin App bileşeni içinde kullanıldığını gösterir.
  • App bileşenini son olarak export ile dışa aktarır, böylece bu bileşen, uygulamanın ana bileşeni olarak kullanılabilir hale gelir. Bu, uygulamanın başlangıç noktasıdır ve diğer bileşenleri içerebilir veya onları çağırabilir.

Veeee mutlu son..

Okumaya devam ettiysen ve buralara kadar geldiysen teşekkür ederim, bir çikolatayı hak ettin demektir. İftar sonrası borcum olsun :))

Bu arada Hayırlı Ramazanlar🌙 🕌 🤲

--

--

Kardel Rüveyda ÇETİN

Expert Software Engineer @DogusTeknoloji ~ All my life I've been over the top. I don't know what I'm doing. All I know is I don't wanna stop. 🤘