pull/439/merge
Samet SARIKAYA 3 months ago committed by GitHub
commit f170dfaa5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

File diff suppressed because it is too large Load Diff

@ -0,0 +1,769 @@
<div align="center">
<h1> 30 Days Of React: Kurulum </h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
</div>
[<< Gün 2](../02_Gun_Reacta_Giris/02_reacta_giris.md) | [Gün 4 >>](../04_Gun_Bilesenler/04_bilesenler.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_3.jpg)
- [Kurulum](#kurulum)
- [Node](#node)
- [Modül](#modül)
- [Paket](#paket)
- [Node Paket Yöneticisi (NPM)](#node-paket-yöneticisi-npm)
- [Visual Studio Code](#visual-studio-code)
- [Tarayıcı](#tarayıcı)
- [Visual Studio Eklentileri](#visual-studio-eklentileri)
- [React Uygulaması Oluşturma](#react-uygulaması-oluşturma)
- [İlk React Uygulamanız](#i̇lk-react-uygulamanız)
- [React Şablonu](#react-şablonu)
- [JSX'te Stil Kullanımı](#jsxte-stil-kullanımı)
- [JSX Elemanlarına Veri Enjekte Etme](#jsx-elemanlarına-veri-enjekte-etme)
- [React'ta Medya Nesnelerini İçe Aktarma](#reactta-medya-nesnelerini-i̇çe-aktarma)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Kurulum
Bir önceki bölümde JSX hakkında bilgi edindik ve CDN aracılığıyla React ile ReactDOM paketlerine eriştik. Ancak gerçek projelerde CDN yerine create-react-app paketini kullanarak bir React projesi başlangıç şablonu (boilerplate) oluşturacaksınız. İlk _create-react-app_, 22 Temmuz 2016'da yayımlandı. Bu tarihten önce geliştiriciler, webpack'i bir JavaScript modül paketleyicisi, babel ve diğer gerekli paketlerle elle yapılandırmak zorundaydı; bu işlem yarım saat ya da daha fazla sürebiliyordu. Artık create-react-app her şeyle ilgilenecek ve siz projeleri yapılandırmaya zaman harcamak yerine yalnızca ürünü geliştirmeye odaklanabileceksiniz. Farklı araçları kullanmaya başlamadan önce bu meydan okumada kullanacağımız araçlara kısa bir giriş yapalım. Her şeyi anlamak zorunda değilsiniz, ancak React ile çalışırken kullandığımız bazı araç ve teknolojileri kısaca tanıtmaya çalışacağım.
## Node
Node, JavaScript'in sunucuda çalışmasını sağlayan bir JavaScript çalışma zamanı ortamıdır. Node, 2009 yılında oluşturuldu ve JavaScript'in büyümesinde büyük bir rol oynadı. React uygulamaları varsayılan olarak localhost 3000 portunda başlar. create-react-app, React uygulaması için bir node sunucusu yapılandırmıştır. Bu nedenle node ve node modüllerine ihtiyaç duyarız. create-react-app'i yakında göreceğiz.
Node kurulu değilse kurun. [node.js](https://nodejs.org/en/) adresinden yükleyin.
![Node download](../../images/download_node.png)
İndirdikten sonra çift tıklayarak kurun.
![Install node](../../images/install_node.png)
Node'un yerel makinemizde kurulu olup olmadığını, cihazımızın terminalini veya komut istemcisini açıp aşağıdaki komutu yazarak kontrol edebiliriz:
```sh
asabeneh $ node -v
v12.18.0
```
## Modül
Tek veya birden fazla fonksiyon, gerektiğinde dışa ve içe aktarılarak bir projeye dahil edilebilir.
React'ta modüllere veya paketlere erişmek için link kullanmayız; bunun yerine modülü içe aktarırız. Bir modülü ya da modülleri nasıl içe ve dışa aktarabileceğimize bakalım:
```js
// math.js
export const addTwo = (a, b) => a + b;
export const multiply = (a, b) => a * b;
export const subtract = (a, b) => a - b;
export default (function doSomeMath() {
return {
addTwo,
multiply,
subtract,
};
})();
```
Şimdi _math.js_ modüllerini farklı bir dosyaya içe aktaralım:
```js
// index.js
// doSomeMath'i math.js dosyasından uzantıyla veya uzantısız içe aktarmak için
import doSomeMath from "./math.js";
// diğer modülleri içe aktarmak için
// bu modüller varsayılan olarak dışa aktarılmadığından destructuring kullanmamız gerekiyor
import { addTwo, multiply, subtract } from "./math.js";
import * as everything from "./math.js"; // geri kalan her şeyi içe aktarmak için
console.log(addTwo(5, 5));
console.log(doSomeMath.addTwo(5, 5));
console.log(everything);
```
Bundan sonra _import React from 'react'_ veya _import ReactDOM from 'react-dom'_ gördüğünüzde şaşırmayacaksınız.
## Paket
Bir paket, tek bir modül ya da modüller topluluğudur. Örneğin React ve ReactDOM birer pakettir.
## Node Paket Yöneticisi (NPM)
NPM, 2010 yılında oluşturuldu. NPM'i ayrıca kurmanıza gerek yoktur; node kurduğunuzda NPM de otomatik olarak yüklenir. NPM, Node.js için varsayılan paket yöneticisidir. Kullanıcıların kayıt defterinde bulunan JavaScript modüllerini tüketmesine ve dağıtmasına olanak tanır. NPM ile paket oluşturabilir, kullanabilir ve dağıtabilirsiniz. NPM de JavaScript'in büyümesinde oldukça büyük bir rol oynadı. Şu anda NPM kayıt defterinde 350.000'den fazla paket bulunmaktadır. NPM kayıt defterinde create-react-app'e bakalım. İndirme sayısı paketin ne kadar popüler olduğunu gösterir.
![NPM create-react-app](../../images/npm_registry.png)
## Visual Studio Code
Kod düzenleyici olarak Visual Studio Code kullanacağız. Henüz kurulu değilse [indirin](https://code.visualstudio.com) ve kurun.
## Tarayıcı
Google Chrome kullanacağız.
## Visual Studio Eklentileri
Visual Studio Code'dan şu eklentileri kurmanız gerekebilir:
- Prettier
- ESLint
- Bracket Pair Colorizer
- ES7 React/Redux/GraphQL/React-Native snippets
## React Uygulaması Oluşturma
Bir React projesi oluşturmak için aşağıdaki yollardan birini kullanabilirsiniz. Node'u kurduğunuzu varsayalım. Mac veya Linux'ta komut satırı arayüzünü (CLI), git bash'i ya da terminali açın. Ardından aşağıdaki komutu çalıştırın. Ben git bash kullanıyorum.
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop
$ npx create-react-app name-of-your-project
```
Her proje oluştururken npx yazmak istemiyorsanız create-react-app paketini bilgisayarınıza global olarak şu komutla kurabilirsiniz:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop
$ npm install -g create-react-app
```
create-react-app'i kurduktan sonra React uygulamasını şu şekilde oluşturabilirsiniz:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop
$ create-react-app name-of-project
```
# İlk React Uygulamanız
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~
\$ cd Desktop/
```
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop
\$ npx create-react-app 30-days-of-react
```
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop
\$ cd 30-days-of-react/
```
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react (master)
\$ npm start
```
Artık React uygulamanız localhost 3000'de çalışıyor olmalı. App.js dosyasına gidin ve içeriği bir miktar yazı ekleyerek değiştirin; en son değişiklikleri tarayıcıda göreceksiniz.
Sunucuyu durdurmak için CLI'da Ctrl + C tuşlarına basın.
![React Starting](../../images/react_app_starting.png)
## React Şablonu
create-react-app tarafından oluşturulan React şablonuna bakalım. Yeni bir proje her oluşturduğunuzda create-react-app ve projenin adını çalıştırırsınız.
Aşağıdaki React şablonunda üç klasör bulunur: node_modules, public ve src. Bunların yanı sıra .gitignore, README.md, package.json ve yarn.lock dosyaları da mevcuttur. Bazılarınızda yarn.lock yerine package-lock.json olabilir.
Bu klasörleri ve dosyaları bilmek faydalıdır.
- node_modules - React uygulamasının tüm gerekli node paketlerini saklar.
- Public
- index.html - uygulamanın tamamında sahip olduğumuz tek HTML dosyası
- favicon.ico - bir simge dosyası
- manifest.json - uygulamayı progressive web uygulaması yapmak için kullanılır
- diğer görseller - open graph görselleri (sosyal medyada bir bağlantı paylaşıldığında görünen görseller)
- robots.txt - web sitesinin web kazımasına izin verip vermediğine dair bilgi
- src
- App.css, index.css - farklı CSS dosyaları
- index.js - tüm bileşenleri index.html ile bağlamaya yarayan dosya
- App.js - genellikle sunum bileşenlerinin çoğunu içe aktardığımız dosya
- serviceWorker.js: progressive web uygulama özelliklerini eklemek için kullanılır
- setupTests.js - test senaryoları yazmak için
- package.json - Uygulamanın kullandığı paketlerin listesi
- .gitignore - React şablonu git ile başlatılmış olarak gelir; .gitignore, bazı dosya ve klasörlerin GitHub'a gönderilmesini engeller
- README.md - Belgeleme yazmak için kullanılan Markdown dosyası
- yarn.lock veya package-lock.json - paket sürümünü sabitlemek için kullanılan bir araç
![React Boilerplate](../../images/react_boilerplate.png)
Şimdi şu an ihtiyacımız olmayan tüm dosyaları kaldıralım ve yalnızca ihtiyaç duyduğumuz dosyaları bırakalım.
Dosyaların büyük bölümünü kaldırdıktan sonra şablonun yapısı şöyle görünür:
![React Boilerplate Cleaned](../../images/react_bolier_plate_cleaned.png)
Şimdi index.js üzerinde kod yazmaya başlayalım. Her şeyden önce React ve ReactDOM'u içe aktarmamız gerekir. React, JSX yazmamıza; ReactDOM ise JSX'i DOM üzerinde render etmemize olanak tanır. ReactDOM'un bir render metodu vardır. Gün 2'de oluşturduğumuz tüm JSX elemanlarını kullanalım. ReactDOM render metodu iki parametre alır: bir JSX ya da bileşen ve kök eleman.
```js
//index.js
// react ve react-dom paketlerini içe aktarma
import React from "react";
import ReactDOM from "react-dom";
const jsxElement = <h1>This is a JSX element</h1>;
const rootElement = document.getElementById("root");
ReactDOM.render(jsxElement, rootElement);
```
```html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500|Roboto:300,400,500&display=swap"
rel="stylesheet"
/>
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>30 Days Of React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
```
Uygulamanız çalışmıyorsa proje klasörünüze gidin ve aşağıdaki komutu çalıştırın:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react (master)
\$ npm start
```
Herhangi bir hata yoksa React uygulamanız tarayıcıda başlatılacaktır.
![JSX using create react app](../../images/jsx_use_create_react_app.png)
Daha fazla JSX elemanı yazalım ve bunları tarayıcıda render edelim. Bu ifade, h2 HTML elemanından oluşan bir JSX elemanıdır.
```js
const title = <h2>Getting Started React</h2>;
```
Önceki JSX'e daha fazla içerik ekleyelim ve adını header olarak değiştirelim.
```js
const header = (
<header>
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
</header>
);
```
Bunu tarayıcıda render etmek için ReactDOM'a ihtiyacımız var.
```js
//index.js
// react ve react-dom paketlerini içe aktarma
import React from "react";
import ReactDOM from "react-dom";
const header = (
<header>
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 2, 2020</small>
</header>
);
const rootElement = document.getElementById("root");
ReactDOM.render(header, rootElement);
```
![JSX using create react app](../../images/rendering_more_jsx_content_create_react_app.png)
Şimdi Gün 2'de oluşturduğumuz tüm JSX'i ekleyelim.
```js
//index.js
// react ve react-dom paketlerini içe aktarma
import React from "react";
import ReactDOM from "react-dom";
// JSX element, header
const header = (
<header>
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 2, 2020</small>
</header>
);
// JSX element, main
const main = (
<main>
<p>Prerequisite to get started react.js:</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</main>
);
// JSX element, footer
const footer = (
<footer>
<p>Copyright 2020</p>
</footer>
);
// JSX element, app, a container or a parent
const app = (
<div>
{header}
{main}
{footer}
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
// ReactDOM'un render metodu iki argüman alır
ReactDOM.render(app, rootElement);
// ya da
// ReactDOM.render([header, main, footer], rootElement)
```
![JSX using create react app to render more jsx](../../images/rendering_multiple_jsx_elements_create-react_app.png)
## JSX'te Stil Kullanımı
JSX elemanlarına stil uygulayalım. JSX'i satır içi, dahili veya harici CSS stilleriyle stillendirebiliriz. Şimdi her JSX elemanına satır içi stiller uygulayalım.
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
const headerStyles = {
backgroundColor: "#61DBFB",
fontFamily: "Helvetica Neue",
padding: 25,
lineHeight: 1.5,
};
// JSX element, header
const header = (
<header style={headerStyles}>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 2, 2020</small>
</div>
</header>
);
// JSX element, main
const mainStyles = {
backgroundColor: "#F3F0F5",
};
const main = (
<main style={mainStyles}>
<p>Prerequisite to get started react.js:</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</main>
);
const footerStyles = {
backgroundColor: "#61DBFB",
};
// JSX element, footer
const footer = (
<footer style={footerStyles}>
<p>Copyright 2020</p>
</footer>
);
// JSX element, app
const app = (
<div className="app">
{header}
{main}
{footer}
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
ReactDOM.render(app, rootElement);
```
![Inline styling JSX](../../images/styling_jsx_inline_create_react_app.png)
Şimdi dahili bir stil uygulayalım; tüm CSS'i index.html'in başlık kısmına taşıyalım.
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// JSX element, header
const header = (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Instructor: Asabeneh Yetayeh</p>
<small>Date: Oct 1, 2020</small>
</div>
</header>
);
// JSX element, main
const main = (
<main>
<div className="main-wrapper">
<p>
Prerequisite to get started{" "}
<strong>
<em>react.js</em>
</strong>
:
</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li> JavaScript</li>
</ul>
</div>
</main>
);
// JSX element, footer
const footer = (
<footer>
<div className="footer-wrapper">
<p>Copyright 2020</p>
</div>
</footer>
);
// JSX element, app
const app = (
<div className="app">
{header}
{main}
{footer}
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
ReactDOM.render(app, rootElement);
```
![Inline styling JSX](../../images/js_internal_style_create_react_app.png)
## JSX Elemanlarına Veri Enjekte Etme
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// HTML belgesinden kök elemanı almak için
// JSX element, header
const welcome = "Welcome to 30 Days Of React";
const title = "Getting Started React";
const subtitle = "JavaScript Library";
const author = {
firstName: "Asabeneh",
lastName: "Yetayeh",
};
const date = "Oct 2, 2020";
// JSX element, header
const header = (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
Instructor: {author.firstName} {author.lastName}
</p>
<small>Date: {date}</small>
</div>
</header>
);
const numOne = 3;
const numTwo = 2;
const result = (
<p>
{numOne} + {numTwo} = {numOne + numTwo}
</p>
);
const yearBorn = 1820;
const currentYear = new Date().getFullYear();
const age = currentYear - yearBorn;
const personAge = (
<p>
{" "}
{author.firstName} {author.lastName} is {age} years old
</p>
);
// JSX element, main
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li>{tech}</li>);
// JSX element, main
const main = (
<main>
<div className="main-wrapper">
<p>
Prerequisite to get started{" "}
<strong>
<em>react.js</em>
</strong>
:
</p>
<ul>{techsFormatted}</ul>
{result}
{personAge}
</div>
</main>
);
const copyRight = "Copyright 2020";
// JSX element, footer
const footer = (
<footer>
<div className="footer-wrapper">
<p>{copyRight}</p>
</div>
</footer>
);
// JSX element, app
const app = (
<div className="app">
{header}
{main}
{footer}
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
ReactDOM.render(app, rootElement);
```
![Inline styling JSX](../../images/inecting_data_to_jsx_create_react_app.png)
## React'ta Medya Nesnelerini İçe Aktarma
React'ta görseller, video ve ses dosyaları nasıl içe aktarılır? Önce görsellerin nasıl içe aktarıldığına bakalım.
src klasörü içinde images adında bir klasör oluşturun ve içine bir görsel kaydedin. Örneğin asabeneh.jpg görselini kaydedip index.js dosyasına aktaralım. İçe aktardıktan sonra bunu bir JSX ifadesine, user değişkenine enjekte edeceğiz. Aşağıdaki koda bakın.
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import asabenehImage from "./images/asabeneh.jpg";
const user = (
<div>
<img src={asabenehImage} alt="asabeneh image" />
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
ReactDOM.render(user, rootElement);
```
![Rendering image](../../images/rendering_image.png)
user'ı ana JSX elemanının içine enjekte edip sonucu görelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// HTML belgesinden kök elemanı almak için
import asabenehImage from "./images/asabeneh.jpg";
// JSX element, header
const welcome = "Welcome to 30 Days Of React";
const title = "Getting Started React";
const subtitle = "JavaScript Library";
const author = {
firstName: "Asabeneh",
lastName: "Yetayeh",
};
const date = "Oct 2, 2020";
// JSX element, header
const header = (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
Instructor: {author.firstName} {author.lastName}
</p>
<small>Date: {date}</small>
</div>
</header>
);
const numOne = 3;
const numTwo = 2;
const result = (
<p>
{numOne} + {numTwo} = {numOne + numTwo}
</p>
);
const yearBorn = 1820;
const currentYear = new Date().getFullYear();
const age = currentYear - yearBorn;
const personAge = (
<p>
{" "}
{author.firstName} {author.lastName} is {age} years old
</p>
);
// JSX element, main
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li>{tech}</li>);
const user = (
<div>
<img src={asabenehImage} alt="asabeneh image" />
</div>
);
// JSX element, main
const main = (
<main>
<div className="main-wrapper">
<p>
Prerequisite to get started{" "}
<strong>
<em>react.js</em>
</strong>
:
</p>
<ul>{techsFormatted}</ul>
{result}
{personAge}
{user}
</div>
</main>
);
const copyRight = "Copyright 2020";
// JSX element, footer
const footer = (
<footer>
<div className="footer-wrapper">
<p>{copyRight}</p>
</div>
</footer>
);
// JSX element, app
const app = (
<div className="app">
{header}
{main}
{footer}
</div>
);
const rootElement = document.getElementById("root");
// JSX elemanını ReactDOM paketi kullanarak render ediyoruz
ReactDOM.render(app, rootElement);
```
![All JSX together final](../../images/all_jsx_final.png)
Şablon kodunu [buradan](../../03_Day_Setting_Up/30-days-of-react_boilerplate) bulabilirsiniz.
# Egzersizler
## Egzersizler: Seviye 1
1. Modül nedir?
2. Paket nedir?
3. Modül ile paket arasındaki fark nedir?
4. NPM nedir?
5. Webpack nedir?
6. Yeni bir React projesi nasıl oluşturulur?
7. Bir proje klasörünün içindeki dosya ve klasörler nelerdir (package.json, package-lock.json veya yarn.lock, .gitignore, node_modules ve public)?
8. En sevdiğiniz kod düzenleyici nedir (Visual Studio Code olduğuna inanıyorum)?
9. Verimliliğinizi artırmak için farklı Visual Studio Code eklentileri ekleyin (örneğin Prettier, ESLint vb.).
10. Farklı bir dosyada özel bir modül oluşturmayı ve onu index.js dosyasına aktarmayı deneyin.
## Egzersizler: Seviye 2
1. Aşağıdaki görseli içe aktarın ve render edin.
![Front end](../../images/frontend_technologies.png)
2. h1, p, input ve button HTML elemanlarını kullanarak JSX ile aşağıdaki tasarımı oluşturun.
![News Letter](../../images/news_letter_design.png)
## Egzersizler: Seviye 3
1. Aşağıdaki kullanıcı kartını tasarlayın.
![User Card](../../images/user_card_design_jsx.png)
🎉 TEBRİKLER! 🎉
[<< Gün 2](../02_Gun_Reacta_Giris/02_reacta_giris.md) | [Gün 4 >>](../04_Gun_Bilesenler/04_bilesenler.md)

@ -0,0 +1,520 @@
<div align="center">
<h1> 30 Days Of React: Bileşenler </h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 3](../03_Gun_Kurulum/03_kurulum.md) | [Gün 5 >>](../05_Gun_Props/05_props.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_4.jpg)
- [Bileşenler](#bileşenler)
- [React'ın Büyük Resmi](#reactın-büyük-resmi)
- [JavaScript fonksiyonu](#javascript-fonksiyonu)
- [JavaScript Class](#javascript-class)
- [React Bileşeni Oluşturma](#react-bileşeni-oluşturma)
- [Functional Component](#functional-component)
- [Bileşenleri Render Etme](#bileşenleri-render-etme)
- [JSX'e Veri Ekleme](#jsxe-veri-ekleme)
- [Functional Component'lere Daha Fazla Bakış](#functional-componentlere-daha-fazla-bakış)
- [Egzersizler: Bileşenler](#egzersizler-bileşenler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Bileşenler
Bir React bileşeni, uygulamanın kullanıcı arayüzünün bir bölümünden sorumlu olan küçük ve yeniden kullanılabilir bir koddur. Bir React uygulaması, bileşenlerin bir araya getirilmesiyle oluşur. React, yeniden kullanılabilir bileşenler oluşturmamıza yardımcı olur. Aşağıdaki diyagram farklı bileşenleri göstermektedir. Tüm bileşenlerin farklı renklerde kenarlıkları vardır. React'ta bir uygulama oluşturmak için farklı bileşenleri bir araya getiririz. Bileşenler oluşturmak için JavaScript fonksiyonlarını veya class'larını kullanırız. Bir fonksiyon kullanırsak bileşen Functional Component olur; bir class kullanırsak class tabanlı bileşen olur.
Bileşenler şu şekilde sınıflandırılabilir:
- Functional Component / Presentational Component / Stateless Component / Dumb Component
- Class Component / Container Component / Statefull Component / Smart Component
Yukarıdaki bileşen sınıflandırması React'ın en son sürümü için geçerli değildir; ancak önceki tanımı ve önceki sürümlerin nasıl çalıştığını bilmek faydalıdır.
O hâlde tüm JSX'leri bileşenlere dönüştürelim. React'taki bileşenler, JSX döndüren JavaScript fonksiyonları veya class'larıdır. Bileşen adı büyük harfle başlamalıdır; ad iki kelimeden oluşuyorsa CamelCase — iki hörgüçlü deve — yazım biçimi kullanılmalıdır.
## React'ın Büyük Resmi
Önceki bölümde bir web sitesinin veya uygulamanın butonlardan, formlardan, metinlerden, medya nesnelerinden, başlık, bölüm, makale ve altbilgiden oluştuğu konusunda hemfikir olduk. Eğer milyon dolarlık bir butonumuz varsa, her ihtiyaç duyduğumuzda sıfırdan oluşturmak yerine bu butonu her zaman kullanabiliriz. Aynı durum giriş alanları, formlar, üstbilgi veya altbilgi için de geçerlidir. İşte bileşenin gücü buradan gelir. Aşağıdaki diyagramda üstbilgi, ana içerik ve altbilgi birer bileşendir. Ana içeriğin içinde ayrıca bir kullanıcı kartı bileşeni ve bir metin bölümü bileşeni bulunmaktadır. Farklı renkler farklı bileşenleri temsil etmektedir. Kaç renk görüyorsunuz? Her renk tek bir bileşeni temsil eder. Bu diyagramda beş bileşen mevcuttur.
![Components](../../images/components_example.png)
React bileşenlerine geçmeden önce fonksiyonları ve class'ları kısaca hatırlayalım.
## JavaScript fonksiyonu
Bir JavaScript fonksiyonu ya klasik fonksiyon ya da ok fonksiyonu (arrow function) olabilir. Bu iki fonksiyon tam olarak aynı değildir; aralarında küçük farklılıklar bulunur.
```js
const getUserInfo = (firstName, lastName, country, title, skills) => {
return `${firstName} ${lastName}, a ${title} developer based in ${country}. He knows ${skills.join(
" ",
)} `;
};
// Bu fonksiyonu çağırırken parametrelere ihtiyacımız var
const skills = ["HTML", "CSS", "JS", "React"];
console.log(
getUserInfo("Asabeneh", "Yetayeh", "Finland", "FullStack Developer", skills),
);
```
## JavaScript Class
Bir class, bir nesnenin taslağıdır. Farklı nesneler oluşturmak için bir class'ı örnekleriz (instantiate). Bunun yanı sıra, üst sınıfın tüm metotlarını ve özelliklerini miras alarak alt sınıflar oluşturabiliriz.
```js
class Parent {
constructor(firstName, lastName, country, title) {
// this anahtar kelimesiyle parametreleri bu class nesnesine bağlıyoruz
this.firstName = firstName;
this.lastName = lastName;
this.country = country;
this.title = title;
}
getPersonInfo() {
return `${this.firstName} ${this.lastName}, a ${this.title} developer base in ${this.country} `;
}
parentMethod() {
// kod buraya gelir
}
}
const p1 = new Parent("Asabeneh", "Yetayeh", "Finland", "FullStack Developer");
class Child extends Parent {
constructor(firstName, lastName, country, title, skills) {
super(firstName, lastName, country, title);
this.skills = skills;
// alt sınıf parametrelerini this anahtar kelimesiyle bu alt sınıf nesnesine bağlıyoruz
}
getSkills() {
let len = this.skills.length;
return len > 0 ? this.skills.join(" ") : "No skills found";
}
childMethod() {
// kod buraya gelir
}
}
const skills = ["HTML", "CSS", "JS", "React"];
const child = new Child(
"Asabeneh",
"Yetayeh",
"Finland",
"FullStack Developer",
skills,
);
```
Fonksiyonu ve class'ı kısaca ele aldık. React bileşeni JavaScript fonksiyonlarından veya class'larından oluşur; o hâlde şimdi bir React bileşeni yapalım.
## React Bileşeni Oluşturma
### Functional Component
Bir JavaScript fonksiyonu kullanarak işlevsel (functional) bir React bileşeni oluşturabiliriz.
```js
// React bileşen sözdizimi
// ok fonksiyonu, fonksiyon bildirimi veya fonksiyon ifadesi olabilir
const jsx = <tag> Content </tag>;
const ComponentName = () => {
return jsx;
};
```
Aşağıdaki ifade bir JSX elementidir.
```js
// JSX elementi, header
const header = (
<header style={headerStyles}>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 3, 2020</small>
</div>
</header>
);
// React Component
const Header = () => {
return header;
};
// ya da doğrudan JSX döndürebiliriz
const Header = () => {
return (
<header style={headerStyles}>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 3, 2020</small>
</div>
</header>
);
};
// Yukarıdaki kod şu şekilde de yazılabilir
// JSX açıkça döndürülüyor
const Header = () => (
<header style={headerStyles}>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 3, 2020</small>
</div>
</header>
);
```
### Bileşenleri Render Etme
Şimdi sahip olduğumuz tüm JSX elementlerini bileşenlere dönüştürelim. Bir JSX elementi çağırırken süslü parantez kullanırız; bileşen çağırırken ise şu şekilde yaparız: `<ComponentName />`. Bileşen adını çağırırken bir özellik (attribute) geçirirsek buna props diyoruz (`<ComponentName propsName={'data-type'} />`). Props konusunu başka bir bölümde ele alacağız. [Code pen'de Canlı İzle](https://codepen.io/Asabeneh/full/wvaKKEM)
Önce _Header_ bileşenini render edelim.
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Header Component
const Header = () => (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 3, 2020</small>
</div>
</header>
);
const rootElement = document.getElementById("root");
// JSX elementini ReactDOM paketiyle render ediyoruz
ReactDOM.render(<Header />, rootElement);
```
Şimdi Header, Main ve Footer bileşenlerini sarmalayacak bir App bileşeni oluşturalım. Ardından App bileşeni DOM'a render edilecek.
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import asabenehImage from "./images/asabeneh.jpg";
// Header Component
const Header = () => (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 3, 2020</small>
</div>
</header>
);
// User Card Component
const UserCard = () => (
<div className="user-card">
<img src={asabenehImage} alt="asabeneh image" />
<h2>Asabeneh Yetayeh</h2>
</div>
);
// TechList Component
const TechList = () => {
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
};
// Main Component
const Main = () => (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList />
</ul>
<UserCard />
</div>
</main>
);
// Footer Component
const Footer = () => (
<footer>
<div className="footer-wrapper">
<p>Copyright 2020</p>
</div>
</footer>
);
// App, yani üst veya kapsayıcı bileşen
const App = () => (
<div className="app">
<Header />
<Main />
<Footer />
</div>
);
const rootElement = document.getElementById("root");
// App bileşenini ReactDOM paketiyle render ediyoruz
ReactDOM.render(<App />, rootElement);
```
![Rendering Components](../../images/rendering_componnets.png)
### JSX'e Veri Ekleme
Şimdiye kadar JSX elementlerinde statik veri kullandık. Şimdi farklı veri tiplerini dinamik veri olarak geçirelim. Dinamik veri; string, sayı, boolean, dizi veya nesne olabilir. Her veri tipini adım adım inceleyelim. JSX'e veri eklemek için `{}` parantezini kullanırız.
Bu bölümde yalnızca string ekliyoruz.
```js
import React from "react";
import ReactDOM from "react-dom";
const welcome = "Welcome to 30 Days Of React";
const title = "Getting Started React";
const subtitle = "JavaScript Library";
const firstName = "Asabeneh";
const lastName = "Yetayeh";
const date = "Oct 3, 2020";
// JSX elementi, header
const header = () => {
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
Instructor: {firstName} {lastName}
</p>
<small>Date: {date}</small>
</div>
</header>
);
};
const rootElement = document.getElementById("root");
// App bileşenini ReactDOM paketiyle render ediyoruz
ReactDOM.render(<Header />, rootElement);
```
Header bileşenine benzer şekilde Main ve Footer bileşenlerine de uygulayabiliriz.
```js
// HTML belgesinden kök elementi alıyoruz
const rootElement = document.querySelector(".root");
// JSX elementi, header
const welcome = "Welcome to 30 Days Of React Challenge";
const title = "Getting Started React";
const subtitle = "JavaScript Library";
const author = {
firstName: "Asabeneh",
lastName: "Yetayeh",
};
const date = "Oct 2, 2020";
// JSX elementi, header
const Header = () => (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
Instructor: {author.firstName} {author.lastName}
</p>
<small>Date: {date}</small>
</div>
</header>
);
const numOne = 3;
const numTwo = 2;
const result = (
<p>
{numOne} + {numTwo} = {numOne + numTwo}
</p>
);
const yearBorn = 1820;
const currentYear = 2020;
const age = currentYear - yearBorn;
const personAge = (
<p>
{" "}
{author.firstName} {author.lastName} is {age} years old
</p>
);
// User Card Component
const UserCard = () => (
<div className="user-card">
<img src={asabenehImage} alt="asabeneh image" />
<h2>
{author.firstName} {author.lastName}
</h2>
</div>
);
// JSX elementi, main
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
// JSX elementi, main
const Main = () => (
<main>
<div className="main-wrapper">
<div>
<p>
Prerequisite to get started{" "}
<strong>
<em>react.js</em>
</strong>
:
</p>
<ul>{techsFormatted}</ul>
{result}
{personAge}
</div>
<UserCard />
</div>
</main>
);
const copyRight = "2020";
// JSX elementi, footer
const Footer = () => (
<footer>
<div className="footer-wrapper">
<p>Copyright &copy;{copyRight}</p>
</div>
</footer>
);
// JSX elementi, app
const app = () => (
<div className="app">
<Header />
<Main />
<Footer />
</div>
);
// App bileşenini ReactDOM paketiyle render ediyoruz
ReactDOM.render(<App />, rootElement);
```
### Functional Component'lere Daha Fazla Bakış
2. Gün'deki tüm JSX elementlerini Functional Component'lere dönüştürdük; artık bileşenlere oldukça aşinasınız. Daha fazla bileşen oluşturalım. Bir bileşenin en küçük boyutu nedir? Yalnızca tek bir HTML öğesi döndüren JSX, küçük bileşen olarak kabul edilir. Örneğin bir buton bileşeni, bir uyarı kutusu bileşeni ya da yalnızca bir giriş alanı bileşeni.
```js
const Button = () => <button>action</button>;
```
_Button_ bileşeni tek bir HTML buton öğesinden oluşmaktadır.
Bu butonu JavaScript stil nesnesi kullanarak biçimlendirelim. Bir JavaScript CSS nesnesi oluşturmak için tüm CSS özellikleri camelCase biçiminde yazılmalıdır. Birim belirtilmeden sayı geçirilirse bu değer px olarak kabul edilir. Aşağıdaki örneğe bakın.
```js
const buttonStyles = {
padding: "10px 20px",
background: "rgb(0, 255, 0",
border: "none",
borderRadius: 5,
};
const Button = () => <button style={buttonStyles}> action </button>;
```
Button bileşeni hiçbir parametre almadığı ve aksiyon metnini dinamik olarak değiştiremediğimiz için aptal bir bileşendir (dumb component). Değerin dinamik olarak değişebilmesi için butona props geçmemiz gerekir. Props konusunu bir sonraki bölümde inceleyeceğiz. Bugünkü dersi kapatmadan önce rastgele bir onaltılık (hexadecimal) renk sayısı görüntüleyen daha işlevsel bir bileşen daha yapalım.
```js
import React from "react";
import ReactDOM from "react-dom";
// Onaltılık renk üreteci
const hexaColor = () => {
let str = "0123456789abcdef";
let color = "";
for (let i = 0; i < 6; i++) {
let index = Math.floor(Math.random() * str.length);
color += str[index];
}
return "#" + color;
};
const HexaColor = () => <div>{hexaColor()}</div>;
const rootElement = document.getElementById("root");
// App bileşenini ReactDOM paketiyle render ediyoruz
ReactDOM.render(<HexaColor />, rootElement);
```
# Egzersizler: Bileşenler
## Egzersizler: Seviye 1
1. Klasik fonksiyon ile ok fonksiyonu arasındaki fark nedir?
2. React Bileşeni nedir?
3. React Functional Component nasıl oluşturulur?
4. Saf bir JavaScript fonksiyonu ile Functional Component arasındaki fark nedir?
5. Bir React bileşeni en küçük boyutuyla ne kadardır?
6. Bir buton veya giriş alanı bileşeni oluşturabilir miyiz?
7. Yeniden kullanılabilir bir Button bileşeni oluşturun.
8. Yeniden kullanılabilir bir InputField bileşeni oluşturun.
9. Bir üst div elementi ve bir alt p elementi içeren yeniden kullanılabilir bir uyarı kutusu bileşeni oluşturun (uyarı kutusu, başarı kutusu).
## Egzersizler: Seviye 2
1. Functional Component oluşturun ve aşağıdaki görselleri görüntüleyin.
![Front end](../../images/frontend_technologies.png)
2. Aşağıdaki tasarımı oluşturmak için Functional Component kullanın.
![News Letter](../../images/news_letter_design.png)
## Egzersizler: Seviye 3
1. Örnekte verilen onaltılık renk üretecini kullanarak aşağıdaki rastgele renkleri oluşturun.
![Hexadecimal colors](../../images/hexadecimal_color_exercise.png)
2. Aşağıdaki kullanıcı kartını tasarlamak için Functional Component kullanın.
![User Card](../../images/user_card_design_jsx.png)
🎉 TEBRİKLER ! 🎉
[<< Gün 3](../03_Gun_Kurulum/03_kurulum.md) | [Gün 5 >>](../05_Gun_Props/05_props.md)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,288 @@
<div align="center">
<h1> 30 Days Of React: Dizileri Haritalama (Mapping Arrays) </h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 5](../05_Gun_Props/05_props.md) | [Gün 7 >>](../07_Gun_Class_Bilesenler/07_class_bilesenler.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_6.jpg)
- [Dizileri Haritalama (Mapping Arrays)](#dizileri-haritalama-mapping-arrays)
- [Dizi haritalama ve render etme](#dizi-haritalama-ve-render-etme)
- [Sayı dizisini haritalama](#sayı-dizisini-haritalama)
- [Dizi içinde diziyi haritalama](#dizi-içinde-diziyi-haritalama)
- [Nesne dizisini haritalama](#nesne-dizisini-haritalama)
- [Dizi haritalamada key (anahtar)](#dizi-haritalamada-key-anahtar)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Dizileri Haritalama (Mapping Arrays)
Dizi, birçok farklı problemi çözmek için en sık kullanılan veri yapısıdır. React'ta, bir dizideki her elemana belirli HTML element'leri ekleyerek bu diziyi JSX listesine dönüştürmek için map kullanırız.
## Dizi haritalama ve render etme
Çoğu zaman veriler bir dizi veya nesne dizisi şeklinde gelir. Bu dizi ya da nesne dizisini render etmek için çoğu zaman _map_ kullanarak veriyi değiştiririz. Önceki bölümde, techs listesini bir map metodu kullanarak render etmiştik. Bu bölümde daha fazla örnek göreceğiz.
Aşağıdaki örneklerde, tarayıcıda sayı dizisi, string dizisi, ülkeler dizisi ve beceriler dizisini nasıl render edeceğimizi göreceksiniz.
```js
import React from "react";
import ReactDOM from "react-dom";
const App = () => {
return (
<div className="container">
<div>
<h1>Numbers List</h1>
{[1, 2, 3, 4, 5]}
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Tarayıcıyı kontrol ederseniz, sayıların tek bir satırda birbirine yapışık göründüğünü görürsünüz. Bunu önlemek için diziyi değiştiririz ve dizi elemanlarını JSX elementine çeviririz. Aşağıdaki örnekte, dizi bir JSX elemanları listesine dönüştürülmüştür.
### Sayı dizisini haritalama
```js
import React from "react";
import ReactDOM from "react-dom";
const Numbers = ({ numbers }) => {
// diziyi li JSX dizisine dönüştürme
const list = numbers.map((number) => <li>{number}</li>);
return list;
};
// App component (Bileşeni)
const App = () => {
const numbers = [1, 2, 3, 4, 5];
return (
<div className="container">
<div>
<h1>Numbers List</h1>
<ul>
<Numbers numbers={numbers} />
</ul>
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
### Dizi içinde diziyi haritalama
Dizi içinde dizi nasıl haritalanır görelim:
```js
import React from "react";
import ReactDOM from "react-dom";
const skills = [
["HTML", 10],
["CSS", 7],
["JavaScript", 9],
["React", 8],
];
// Skill Component (Bileşeni)
const Skill = ({ skill: [tech, level] }) => (
<li>
{tech} {level}
</li>
);
// Skills Component (Bileşeni)
const Skills = ({ skills }) => {
const skillsList = skills.map((skill) => <Skill skill={skill} />);
console.log(skillsList);
return <ul>{skillsList}</ul>;
};
const App = () => {
return (
<div className="container">
<div>
<h1>Skills Level</h1>
<Skills skills={skills} />
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
### Nesne dizisini haritalama
Nesne dizisini render etme:
```js
import React from "react";
import ReactDOM from "react-dom";
const countries = [
{ name: "Finland", city: "Helsinki" },
{ name: "Sweden", city: "Stockholm" },
{ name: "Denmark", city: "Copenhagen" },
{ name: "Norway", city: "Oslo" },
{ name: "Iceland", city: "Reykjavík" },
];
// Country component (Bileşeni)
const Country = ({ country: { name, city } }) => {
return (
<div>
<h1>{name}</h1>
<small>{city}</small>
</div>
);
};
// Countries component (Bileşeni)
const Countries = ({ countries }) => {
const countryList = countries.map((country) => <Country country={country} />);
return <div>{countryList}</div>;
};
// App component (Bileşeni)
const App = () => (
<div className="container">
<div>
<h1>Countries List</h1>
<Countries countries={countries} />
</div>
</div>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
### Dizi haritalamada key (anahtar)
Key'ler (Anahtarlar), React'ın hangi elemanların değiştiğini, eklendiğini veya kaldırıldığını tanımlamasına yardımcı olur. Dizi içindeki elemanlara, o elemanlara kararlı bir kimlik kazandırmak için key verilmelidir. Key benzersiz olmalıdır. Çoğu zaman veriler bir id ile birlikte gelir ve bu id'yi key olarak kullanabiliriz. React'a haritalama sırasında key geçirmezsek tarayıcıda bir uyarı üretilir. Verinin id'si yoksa, haritalama sırasında her eleman için benzersiz bir tanımlayıcı oluşturmanın bir yolunu bulmamız gerekir. Aşağıdaki örneğe bakın:
```js
import React from "react";
import ReactDOM from "react-dom";
const Numbers = ({ numbers }) => {
// diziyi li JSX dizisine dönüştürme
const list = numbers.map((num) => <li key={num}>{num}</li>);
return list;
};
const App = () => {
const numbers = [1, 2, 3, 4, 5];
return (
<div className="container">
<div>
<h1>Numbers List</h1>
<ul>
<Numbers numbers={numbers} />
</ul>
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Şimdi ülkeler haritalama örneğine de key ekleyelim:
```js
import React from "react";
import ReactDOM from "react-dom";
const countries = [
{ name: "Finland", city: "Helsinki" },
{ name: "Sweden", city: "Stockholm" },
{ name: "Denmark", city: "Copenhagen" },
{ name: "Norway", city: "Oslo" },
{ name: "Iceland", city: "Reykjavík" },
];
// Country component (Bileşeni)
const Country = ({ country: { name, city } }) => {
return (
<div>
<h1>{name}</h1>
<small>{city}</small>
</div>
);
};
// Countries component (Bileşeni)
const Countries = ({ countries }) => {
const countryList = countries.map((country) => (
<Country key={country.name} country={country} />
));
return <div>{countryList}</div>;
};
const App = () => (
<div className="container">
<div>
<h1>Countries List</h1>
<Countries countries={countries} />
</div>
</div>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
# Egzersizler
## Egzersizler: Seviye 1
1. Neden bir diziyi haritalamamız gerekir?
2. Dizi haritalamada neden key'lere (anahtarlara) ihtiyaç duyarız?
3. Kodunuzu destructuring (parçalama) etmenin önemi nedir?
4. Destructuring (Parçalama) kodunuzu daha temiz ve okunması daha kolay hale getirir mi?
## Egzersizler: Seviye 2
1. Aşağıdaki tasarımda çift sayılar yeşil, tek sayılar sarı ve asal sayılar kırmızıdır. Bu renkleri React Component (Bileşen) kullanarak oluşturun.
![Number Generator](../../images/day_6_number_generater_exercise.png)
2. Aşağıdaki onaltılık (hexadecimal) renkleri React Component (Bileşen) kullanarak oluşturun.
![Number Generator](../../images/day_6_hexadecimal_colors_exercise.png)
## Egzersizler: Seviye 3
1. Verilen [veriyi](../../06_Day_Map_List_Keys/06_map_list_keys_boilerplate/src/data/ten_most_highest_populations.js) kullanarak aşağıdaki çubuk grafiğini oluşturun.
![Ten most highest populations](../../images/day_6_ten_highest_populations_exercise.png)
🎉 TEBRİKLER! 🎉
[<< Gün 5](../05_Gun_Props/05_props.md) | [Gün 7 >>](../07_Gun_Class_Bilesenler/07_class_bilesenler.md)

@ -0,0 +1,844 @@
<div align="center">
<h1> 30 Days Of React: Class Component (Sınıf Tabanlı Bileşenler) </h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 6](../06_Gun_Dizi_Haritalama/06_dizi_haritalama.md) | [Gün 8 >>](../08_Gun_State/08_state.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_7.jpg)
- [Class Component (Sınıf Tabanlı Bileşenler)](#class-component-sınıf-tabanlı-bileşenler)
- [Class Component'ta Props'a Erişim](#class-componentta-propsa-erişim)
- [Class Tabanlı Component'ta Metotlar](#class-tabanlı-componentta-metotlar)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Class Component (Sınıf Tabanlı Bileşenler)
Önceki bölümlerde JSX, Functional Component (Fonksiyonel Bileşen) ve Props (Özellikler) konularını ele aldık. Bu bölümde Class Component (Sınıf Tabanlı Bileşenler) veya stateful component (durumlu bileşen) konusunu ele alacağız. Yalnızca class tabanlı component'lerin state (durum) ve yaşam döngüsü metotları vardı. Ancak React 16.8.0 sürümünden sonra fonksiyonel component'ler de React Hook'ları (Kancalar) kullanarak state ve yaşam döngüsüne sahip olabilmektedir. 30 Days Of React meydan okumasında, hem eski hem yeni sürümü anlamak amacıyla React'ı 16.8.0 öncesi ve sonrasını kapsayacak şekilde ele alacağız. Eski sürümde yazılmış çok sayıda kod var ve bu kodlar belirli bir noktada taşınmayı gerektirebilir. Bunun yanı sıra, React'ı gerçekten iyi anlamak için class tabanlı component'leri de anlamak gerekmektedir.
Şimdiye kadar gördüğümüz tüm component'ler fonksiyonel component'tir. Şimdi class tabanlı component de oluşturalım. Class tabanlı component, JavaScript class'ı kullanılarak yapılır ve React Component'tan kalıtım alır. Daha önce oluşturduğumuz tüm fonksiyonel component'leri dönüştürerek class tabanlı component'in nasıl yapıldığını öğrenelim. Tümünü dönüştürmek zorunlu değildir; ancak fonksiyonel component'lerin class component'e nasıl dönüştürüldüğünü öğrenmek amacıyla bunu yapıyoruz.
```js
// Saf JavaScript class'ı ve child (çocuk) class
// React paketinden import ettiğimizi hayal edin
class Component {
constructor(props) {}
}
// Class tabanlı component'leri bu şekilde üst class'tan kalıtarak yaparız
class Child extends Component {
constructor(props) {
super(props);
}
}
```
Fonksiyonel React Component (Bileşeni):
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Header Component (Bileşeni)
// Fonksiyonel component
const Header = () => (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 6, 2020</small>
</div>
</header>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<Header />, rootElement);
```
Class tabanlı React Component (Bileşeni), React.Component'in bir child'ıdır (çocuğudur); yerleşik bir render metoduna sahiptir ve constructor içerebilir.
```js
//index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
render() {
return (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 7, 2020</small>
</div>
</header>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Header />, rootElement);
```
Yukarıdaki component'i constructor ile görelim:
```js
//index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
return (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 7, 2020</small>
</div>
</header>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Header />, rootElement);
```
Tüm fonksiyonel component'leri class tabanlı component'e dönüştürelim:
```js
// TechList Component (Bileşeni)
// fonksiyonel component
const TechList = () => {
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
};
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
constructor(props) {
super(props);
}
render() {
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Fonksiyonel Component
const Main = () => (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList />
</ul>
</div>
</main>
);
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList />
</ul>
</div>
</main>
);
}
}
// Footer Component (Bileşeni)
// Fonksiyonel component
const Footer = () => (
<footer>
<div className="footer-wrapper">
<p>Copyright 2020</p>
</div>
</footer>
);
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright 2020</p>
</div>
</footer>
);
}
}
// Ana uygulama veya üst (parent) veya kapsayıcı (container) component
// Fonksiyonel Component
const App = () => (
<div className="app">
<Header />
<Main />
<Footer />
</div>
);
// Ana uygulama veya üst (parent) veya kapsayıcı (container) component
// Class Component
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="app">
<Header />
<Main />
<Footer />
</div>
);
}
}
```
Tüm class tabanlı component'leri tek dosyada birleştirelim:
```js
//index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
return (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 7, 2020</small>
</div>
</header>
);
}
}
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
constructor(props) {
super(props);
}
render() {
const techs = ["HTML", "CSS", "JavaScript"];
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList />
</ul>
</div>
</main>
);
}
}
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright 2020</p>
</div>
</footer>
);
}
}
// Ana uygulama veya üst (parent) veya kapsayıcı (container) component
// Class Component
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="app">
<Header />
<Main />
<Footer />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
## Class Component'ta Props'a Erişim
Props (Özellikler)'in, bir component'ten diğerine veri göndermenin yolu olduğunu ya da başka bir deyişle props'un bir veri taşıyıcısı olduğunu belirtmiştik. Bu nedenle, class tabanlı component'te de props'u işlememiz gerekir. Bir class tabanlı component'in props'una _this_ anahtar kelimesini kullanarak erişebiliriz. Aşağıdaki örneğe bakın:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
return (
<header>
<div className="header-wrapper">
<h1>{this.props.data.welcome}</h1>
<h2>{this.props.data.title}</h2>
<h3>
{this.props.data.author.firstName} {this.props.data.author.lastName}
</h3>
<small>{this.props.data.date}</small>
</div>
</header>
);
}
}
const App = () => {
const data = {
welcome: "Welcome to 30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 7, 2020",
};
return (
<div className="app">
<Header data={data} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Yukarıdaki örnekte görüldüğü gibi, props'tan veriyi almak için her seferinde _props.data_ yazmamız gerekiyor. Destructuring (Parçalama) kullanarak bu tekrarı önleyebiliriz:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const App = () => {
const data = {
welcome: "Welcome to 30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 6, 2020",
};
return (
<div className="app">
<Header data={data} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Yukarıdaki kodun bir öncekinden daha temiz olduğunu görebilirsiniz. Şimdi sahip olduğumuz tüm component'leri temizleyip birleştirelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
constructor(props) {
super(props);
}
render() {
const { techs } = this.props;
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList techs={this.props.techs} />
</ul>
</div>
</main>
);
}
}
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright {this.props.date.getFullYear()}</p>
</div>
</footer>
);
}
}
class App extends React.Component {
render() {
const data = {
welcome: "Welcome to 30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 7, 2020",
};
const techs = ["HTML", "CSS", "JavaScript"];
return (
<div className="app">
<Header data={data} />
<Main techs={techs} />
<Footer date={new Date()} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
## Class Tabanlı Component'ta Metotlar
Class tabanlı component'te metotlara erişiriz. Çoğu zaman farklı metotları üst (parent) component'te yazarız ve bunları alt (child) component'lere geçiririz. Uygulamayı görelim.
Bu component'e bir metot ekleyelim:
```js
//index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
greetPeople = () => {
alert("Welcome to 30 Days Of React Challenge, 2020");
};
render() {
return (
<header>
<div className="header-wrapper">
<h1>Welcome to 30 Days Of React</h1>
<h2>Getting Started React</h2>
<h3>JavaScript Library</h3>
<p>Asabeneh Yetayeh</p>
<small>Oct 7, 2020</small>
<button onClick={this.greetPeople}> Greet </button>
</div>
</header>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Header />, rootElement);
```
Metodu çağırmak veya tetiklemek event oluştuğunda gerçekleşir. Bu nedenle bir metodu event listener'a geçirirken metodu çağırmayın (parantez koymayın).
Şimdi sahip olduğumuz koda gerekli tüm metotları ekleyelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import asabenehImage from "./images/asabeneh.jpg";
// User Card Component (Bileşeni)
const UserCard = ({ user: { firstName, lastName, image } }) => (
<div className="user-card">
<img src={image} alt={firstName} />
<h2>
{firstName}
{lastName}
</h2>
</div>
);
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: 3,
cursor: "pointer",
fontSize: 18,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
constructor(props) {
super(props);
}
render() {
const { techs } = this.props;
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList techs={this.props.techs} />
</ul>
<UserCard user={this.props.user} />
<Button
text="Greet People"
onClick={this.props.greetPeople}
style={buttonStyles}
/>
<Button
text="Show Time"
onClick={this.props.handleTime}
style={buttonStyles}
/>
</div>
</main>
);
}
}
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright {this.props.date.getFullYear()}</p>
</div>
</footer>
);
}
}
class App extends React.Component {
showDate = (time) => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = months[time.getMonth()].slice(0, 3);
const year = time.getFullYear();
const date = time.getDate();
return ` ${month} ${date}, ${year}`;
};
handleTime = () => {
alert(this.showDate(new Date()));
};
greetPeople = () => {
alert("Welcome to 30 Days Of React Challenge, 2020");
};
render() {
const data = {
welcome: "Welcome to 30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 7, 2020",
};
const techs = ["HTML", "CSS", "JavaScript"];
// spread operatörü kullanarak data nesnesindeki author'ı user değişkenine kopyalama
const user = { ...data.author, image: asabenehImage };
return (
<div className="app">
<Header data={data} />
<Main
user={user}
techs={techs}
handleTime={this.handleTime}
greetPeople={this.greetPeople}
/>
<Footer date={new Date()} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Çoğu zaman kapsayıcı (container) veya üst (parent) component class component olarak yazılabilir; diğerleri ise fonksiyonel veya sunum (presentational) component olarak yazılabilir. Veri genellikle üst component'ten alt (child) component'e akar ve bu tek yönlüdür. Ancak React'ın en son sürümü, uygulamamızdaki her component'i yalnızca fonksiyonel component'lerle yazmamıza olanak tanımaktadır. Bu, önceki sürümlerde mümkün değildi.
Bir sonraki bölümde, React'ın kalbi olan State (Durum)'u ele alacağız. State (Durum), React component'inin her state değişikliğinde yeniden render edilmesine (tekrar oluşturulmasına) olanak tanır.
# Egzersizler
## Egzersizler: Seviye 1
1. Saf bir JavaScript fonksiyonunu nasıl yazarsınız?
2. Inheritance (Kalıtım) nedir ve bir üst class'tan (parent class) nasıl child class oluşturursunuz?
3. Class tabanlı React Component (Bileşeni) nedir?
4. Fonksiyonel React Component (Bileşeni) ile class tabanlı React Component (Bileşeni) arasındaki fark nedir?
5. Fonksiyonel component'ler yerine class tabanlı component'leri ne zaman kullanmamız gerekir?
6. Class tabanlı component'in kullanım alanları nelerdir?
7. Daha sık hangi tür component kullanırsınız? Fonksiyonel mi, class tabanlı mı?
8. React yaşam döngüsü (life cycle) nedir? (henüz ele alınmadı)
9. React'ta State (Durum) nedir? (henüz ele alınmadı)
## Egzersizler: Seviye 2
Önceki gün egzersizlerini class tabanlı component'lere çevirerek class tabanlı component hakkında daha fazla bilgi edinin.
## Egzersizler: Seviye 3
Yakında...
🎉 TEBRİKLER! 🎉
[<< Gün 6](../06_Gun_Dizi_Haritalama/06_dizi_haritalama.md) | [Gün 8 >>](../08_Gun_State/08_state.md)

@ -0,0 +1,516 @@
<div align="center">
<h1> 30 Days Of React: State (Durum)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 7](../07_Gun_Class_Bilesenler/07_class_bilesenler.md) | [Gün 9 >>](../09_Gun_Kosullu_Render/09_kosullu_render.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_8.jpg)
- [State (Durum)](#state-durum)
- [State (Durum) Nedir?](#state-durum-nedir)
- [State nasıl ayarlanır?](#state-nasıl-ayarlanır)
- [Bir JavaScript metodu ile state'i sıfırlama](#bir-javascript-metodu-ile-statei-sıfırlama)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# State (Durum)
## State (Durum) Nedir?
State nedir? State'in İngilizce anlamı, \_belirli bir anda birisinin veya bir şeyin içinde bulunduğu özel koşul_dur.
State'in bir şeylerin durumu olduğunu görelim:
- Mutlu musunuz yoksa üzgün mü?
- Işık açık mı yoksa kapalı mı?
- Mevcut musunuz yoksa yok musunuz?
- Dolu mu yoksa boş mu?
Örneğin, 30 Days Of React meydan okumasını oluşturmaktan keyif aldığım için mutluyum. Sizin de mutlu olduğunuza inanıyorum.
State (Durum), React'ta state verisi değiştiğinde component'in yeniden render edilmesini sağlayan bir nesnedir.
## State nasıl ayarlanır?
Class tabanlı bir component'in constructor'ı içinde veya dışında bir başlangıç state'i belirleriz. State'i doğrudan değiştirmeyiz ya da mutate etmeyiz; bunun yerine yeni bir state'e sıfırlamak için _setState()_ metodunu kullanırız. Aşağıdaki örnekte görüldüğü gibi, state nesnesinde başlangıç değeri 0 olan count bulunmaktadır. State nesnesine _this.state_ ve özellik adını kullanarak erişebiliriz. Aşağıdaki örneğe bakın:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
// state'i tanımlama
state = {
count: 0,
};
render() {
// state değerine erişme
const count = this.state.count;
return (
<div className="App">
<h1>{count} </h1>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Yukarıdaki kodu çalıştırırsanız tarayıcıda sıfır görürsünüz. JavaScript metodu kullanarak state değerini değiştirerek count değerini artırabilir veya azaltabiliriz.
## Bir JavaScript metodu ile state'i sıfırlama
Şimdi bir düğmeye tıklayarak count değerini artıran veya azaltan bazı metotlar ekleyelim. Artırmak için bir düğme ve azaltmak için bir düğme ekleyelim. State'i ayarlamak için React'ın _this.setState_ metodunu kullanırız. Aşağıdaki örneğe bakın:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
// state'i tanımlama
state = {
count: 0,
};
render() {
// state değerine erişme
const count = this.state.count;
return (
<div className="App">
<h1>{count} </h1>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Add One
</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Yukarıdaki örneği anlarsanız, eksi bir metodu eklemek kolay olacaktır. Click event'e eksi bir metot ekleyelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
// state'i tanımlama
state = {
count: 0,
};
render() {
// state değerine erişme
const count = this.state.count;
return (
<div className="App">
<h1>{count} </h1>
<div>
<button
onClick={() => this.setState({ count: this.state.count + 1 })}
>
Add One
</button>{" "}
<button
onClick={() => this.setState({ count: this.state.count - 1 })}
>
Minus One
</button>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Her iki düğme de iyi çalışıyor; ancak kodu iyi yapılandırmamız gerekiyor. Component'te ayrı metotlar oluşturalım:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
// state'i tanımlama
state = {
count: 0,
};
// state'e bir ekleyen metot
addOne = () => {
this.setState({ count: this.state.count + 1 });
};
// state'ten bir çıkaran metot
minusOne = () => {
this.setState({ count: this.state.count - 1 });
};
render() {
// state değerine erişme
const count = this.state.count;
return (
<div className="App">
<h1>{count} </h1>
<div>
<button className="btn btn-add" onClick={this.addOne}>
+1
</button>{" "}
<button className="btn btn-minus" onClick={this.minusOne}>
-1
</button>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
State hakkında daha fazla örnek yapalım. Aşağıdaki örnekte ya köpek ya da kedi gösteren küçük bir uygulama geliştireceğiz. Başlangıç state'ini kedi olarak ayarlayabiliriz; tıklandığında köpek gösterecek ve bu şekilde devam edecek. Hayvanı dönüşümlü olarak değiştiren bir metoda ihtiyacımız var. Canlı örneği görmek için [buraya](https://codepen.io/Asabeneh/full/LYVxKpq) tıklayın:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
// state'i tanımlama
state = {
image: "https://www.smithsstationah.com/imagebank/eVetSites/Feline/01.jpg",
};
changeAnimal = () => {
let dogURL =
"https://static.onecms.io/wp-content/uploads/sites/12/2015/04/dogs-pembroke-welsh-corgi-400x400.jpg";
let catURL =
"https://www.smithsstationah.com/imagebank/eVetSites/Feline/01.jpg";
let image = this.state.image === catURL ? dogURL : catURL;
this.setState({ image });
};
render() {
return (
<div className="App">
<h1>30 Days Of React</h1>
<div className="animal">
<img src={this.state.image} alt="animal" />
</div>
<button onClick={this.changeAnimal} className="btn btn-add">
Change
</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Şimdi şimdiye kadar sahip olduğumuz tüm kodları bir araya koyalım ve gerekli olduğunda state'i de uygulayalım:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import asabenehImage from "./images/asabeneh.jpg";
// Ay, gün ve yılı gösteren fonksiyon
const showDate = (time) => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = months[time.getMonth()].slice(0, 3);
const year = time.getFullYear();
const date = time.getDate();
return ` ${month} ${date}, ${year}`;
};
// User Card Component (Bileşeni)
const UserCard = ({ user: { firstName, lastName, image } }) => (
<div className="user-card">
<img src={image} alt={firstName} />
<h2>
{firstName}
{lastName}
</h2>
</div>
);
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: 3,
cursor: "pointer",
fontSize: 18,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
constructor(props) {
super(props);
// constructor içindeki kod diğer tüm kodlardan önce çalışır
}
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header style={this.props.styles}>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const Count = ({ count, addOne, minusOne }) => (
<div>
<h1>{count} </h1>
<div>
<Button text="+1" onClick={addOne} style={buttonStyles} />
<Button text="-1" onClick={minusOne} style={buttonStyles} />
</div>
</div>
);
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
constructor(props) {
super(props);
}
render() {
const { techs } = this.props;
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
const {
techs,
user,
greetPeople,
handleTime,
changeBackground,
count,
addOne,
minusOne,
} = this.props;
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList techs={techs} />
</ul>
<UserCard user={user} />
<Button
text="Greet People"
onClick={greetPeople}
style={buttonStyles}
/>
<Button text="Show Time" onClick={handleTime} style={buttonStyles} />
<Button
text="Change Background"
onClick={changeBackground}
style={buttonStyles}
/>
<Count count={count} addOne={addOne} minusOne={minusOne} />
</div>
</main>
);
}
}
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright {this.props.date.getFullYear()}</p>
</div>
</footer>
);
}
}
class App extends React.Component {
state = {
count: 0,
styles: {
backgroundColor: "",
color: "",
},
};
showDate = (time) => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = months[time.getMonth()].slice(0, 3);
const year = time.getFullYear();
const date = time.getDate();
return ` ${month} ${date}, ${year}`;
};
addOne = () => {
this.setState({ count: this.state.count + 1 });
};
// state'ten bir çıkaran metot
minusOne = () => {
this.setState({ count: this.state.count - 1 });
};
handleTime = () => {
alert(this.showDate(new Date()));
};
greetPeople = () => {
alert("Welcome to 30 Days Of React Challenge, 2020");
};
changeBackground = () => {};
render() {
const data = {
welcome: "Welcome to 30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 7, 2020",
};
const techs = ["HTML", "CSS", "JavaScript"];
const date = new Date();
// spread operatörü kullanarak data nesnesindeki author'ı user değişkenine kopyalama
const user = { ...data.author, image: asabenehImage };
return (
<div className="app">
{this.state.backgroundColor}
<Header data={data} />
<Main
user={user}
techs={techs}
handleTime={this.handleTime}
greetPeople={this.greetPeople}
changeBackground={this.changeBackground}
addOne={this.addOne}
minusOne={this.minusOne}
count={this.state.count}
/>
<Footer date={new Date()} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Artık State (Durum) konusunu çok iyi anladığınıza inanıyorum. Bundan sonra diğer bölümlerde de state kullanacağız; çünkü state ve props, React uygulamasının çekirdeğidir.
## Egzersizler
### Egzersizler: Seviye 1
1. Bugün state'iniz nasıldı? Mutlu musunuz? Umarım öyledir. Buraya kadar geldiyseniz mutlu olmalısınız.
2. React'ta State (Durum) nedir?
3. React'ta Props (Özellikler) ve State (Durum) arasındaki fark nedir?
4. Bir React component'inde state'e nasıl erişirsiniz?
5. Bir React component'inde state'i nasıl ayarlarsınız?
### Egzersizler: Seviye 2
1. React state'i kullanarak sayfanın arka plan rengini değiştirin. Bu tekniği portföyünüz için karanlık mod uygulamak amacıyla kullanabilirsiniz.
![Change Background](../../images/08_day_changing_background_exercise.gif)
2. Uzun süredir devam eden kapanmanın ardından seyahat etmeyi düşünüyor olabilirsiniz ve nereye gideceğinizi bilmiyorsunuzdur. Tatil hedefinizi seçen rastgele bir ülke seçici geliştirmek isteyebilirsiniz.
![Change Background](../../images/08_day_select_country_exercise.gif)
### Egzersizler: Seviye 3
Yakında
🎉 TEBRİKLER! 🎉
[<< Gün 7](../07_Gun_Class_Bilesenler/07_class_bilesenler.md) | [Gün 9 >>](../09_Gun_Kosullu_Render/09_kosullu_render.md)

@ -0,0 +1,783 @@
<div align="center">
<h1> 30 Days Of React: Koşullu Render (Conditional Rendering)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 8](../08_Gun_State/08_state.md) | [Gün 10 >>](../10_Gun_Proje_Klasor_Yapisi/10_proje_klasor_yapisi.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_9.jpg)
# Koşullu Render (Conditional Rendering)
Terimden anlaşılacağı gibi, koşullu render (conditional rendering), farklı koşullarda farklı JSX veya component (bileşen) render etmenin bir yoludur. Koşullu render'i sıradan if ve else ifadesini, üçlü (ternary) operatörü ve &&'yi kullanarak uygulayabiliriz. Farklı koşullu render'ları uygulayalım.
## If ve Else İfadesi ile Koşullu Render
Aşağıdaki kodda başlangıç state'i (durumu) false olan loggedIn değişkeni bulunmaktadır. State false ise kullanıcıya giriş yapmasını söyleriz; aksi takdirde kullanıcıyı karşılarız:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
render() {
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
<p>Select a country for your next holiday</p>
</div>
</header>
);
}
}
class App extends React.Component {
state = {
loggedIn: false,
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
// if ve else ifadesi kullanarak koşullu render
let status;
if (this.state.loggedIn) {
status = <h3>Welcome to 30 Days Of React</h3>;
} else {
status = <h3>Please Login</h3>;
}
return (
<div className="app">
<Header data={data} />
{status}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Kullanıcının oturum durumunu değiştirmesine izin veren bir metot ekleyelim. Giriş ve çıkış yapmak için event işleyen bir düğmeye ihtiyacımız var:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: "3px auto",
cursor: "pointer",
fontSize: 22,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
class App extends React.Component {
state = {
loggedIn: false,
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
let status;
let text;
if (this.state.loggedIn) {
status = <h1>Welcome to 30 Days Of React</h1>;
text = "Logout";
} else {
status = <h3>Please Login</h3>;
text = "Login";
}
return (
<div className="app">
<Header data={data} />
{status}
<Button text={text} style={buttonStyles} onClick={this.handleLogin} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Koşulumuz ikiden fazlaysa ne olur? Saf JavaScript'te olduğu gibi if else if ifadesini kullanabiliriz. Genel olarak, koşullu render, saf JavaScript koşullu ifadesinden farklı değildir.
## Üçlü (Ternary) Operatör ile Koşullu Render
Üçlü (ternary) operatör, if else ifadesine bir alternatiftir. Ancak üçlü operatörün if else ifadesinden daha fazla kullanım alanı vardır. Örneğin üçlü operatörü, bir component'teki stil, className ve diğer yerlerde sıradan if else ifadesinden çok daha fazla kullanabilirsiniz:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: "3px auto",
cursor: "pointer",
fontSize: 22,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
render() {
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
class App extends React.Component {
state = {
loggedIn: false,
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
let status = this.state.loggedIn ? (
<h1>Welcome to 30 Days Of React</h1>
) : (
<h3>Please Login</h3>
);
return (
<div className="app">
<Header data={data} />
{status}
<Button
text={this.state.loggedIn ? "Logout" : "Login"}
style={buttonStyles}
onClick={this.handleLogin}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
JSX'e ek olarak, bir component'i de koşullu olarak render edebiliriz. Yukarıdaki koşullu JSX'i bir component'e çevirelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: "3px auto",
cursor: "pointer",
fontSize: 22,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
render() {
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const Login = () => (
<div>
<h3>Please Login</h3>
</div>
);
const Welcome = (props) => (
<div>
<h1>Welcome to 30 Days Of React</h1>
</div>
);
class App extends React.Component {
state = {
loggedIn: false,
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
const status = this.state.loggedIn ? <Welcome /> : <Login />;
return (
<div className="app">
<Header data={data} />
{status}
<Button
text={this.state.loggedIn ? "Logout" : "Login"}
style={buttonStyles}
onClick={this.handleLogin}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
## && Operatörü ile Koşullu Render
&& operatörü, sol operand (ifade) true (doğru) ise sağ JSX operandını render eder:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: "3px auto",
cursor: "pointer",
fontSize: 22,
color: "white",
};
// class tabanlı component
class Header extends React.Component {
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header style={this.props.styles}>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const Login = () => (
<div>
<h3>Please Login</h3>
</div>
);
const Welcome = (props) => (
<div>
<h1>Welcome to 30 Days Of React</h1>
</div>
);
class App extends React.Component {
state = {
loggedIn: false,
techs: ["HTML", "CSS", "JS"],
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
// state'i parçalayabiliriz
const { loggedIn, techs } = this.state;
const status = loggedIn ? <Welcome /> : <Login />;
return (
<div className="app">
<Header data={data} />
{status}
<Button
text={loggedIn ? "Logout" : "Login"}
style={buttonStyles}
onClick={this.handleLogin}
/>
{techs.length === 3 && (
<p>You have all the prerequisite courses to get started React</p>
)}
{!loggedIn && (
<p>
Please login to access more information about 30 Days Of React
challenge
</p>
)}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Önceki bölümde karşılama ve saati alert kutusu olarak göstermiştik. Şimdi karşılamayı ve saati alert kutusu yerine tarayıcı DOM'unda render edelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
// class tabanlı component
class Header extends React.Component {
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header style={this.props.styles}>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const Message = ({ message }) => (
<div>
<h1>{message}</h1>
</div>
);
const Login = () => (
<div>
<h3>Please Login</h3>
</div>
);
const Welcome = (props) => (
<div>
<h1>Welcome to 30 Days Of React</h1>
</div>
);
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
render() {
const { techs } = this.props;
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
render() {
const { techs, greetPeople, handleTime, loggedIn, handleLogin, message } =
this.props;
console.log(message);
const status = loggedIn ? <Welcome /> : <Login />;
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList techs={this.props.techs} />
</ul>
{techs.length === 3 && (
<p>You have all the prerequisite courses to get started React</p>
)}
<div>
<Button
text="Show Time"
onClick={handleTime}
style={buttonStyles}
/>{" "}
<Button
text="Greet People"
onClick={greetPeople}
style={buttonStyles}
/>
{!loggedIn && (
<p>
Please login to access more information about 30 Days Of React
challenge
</p>
)}
</div>
<div style={{ margin: 30 }}>
<Button
text={loggedIn ? "Logout" : "Login"}
style={buttonStyles}
onClick={handleLogin}
/>
<br />
{status}
</div>
<Message message={message} />
</div>
</main>
);
}
}
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: "3px auto",
cursor: "pointer",
fontSize: 22,
color: "white",
};
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright {this.props.date.getFullYear()}</p>
</div>
</footer>
);
}
}
class App extends React.Component {
state = {
loggedIn: false,
techs: ["HTML", "CSS", "JS"],
message: "Click show time or Greet people to change me",
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
showDate = (time) => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = months[time.getMonth()].slice(0, 3);
const year = time.getFullYear();
const date = time.getDate();
return `${month} ${date}, ${year}`;
};
handleTime = () => {
let message = this.showDate(new Date());
this.setState({ message });
};
greetPeople = () => {
let message = "Welcome to 30 Days Of React Challenge, 2020";
this.setState({ message });
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
return (
<div className="app">
<Header data={data} />
<Main
techs={this.state.techs}
handleTime={this.handleTime}
greetPeople={this.greetPeople}
loggedIn={this.state.loggedIn}
handleLogin={this.handleLogin}
message={this.state.message}
/>
<Footer date={new Date()} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
## Tanıklık
Artık Yazar ve 30DaysOfReact hakkındaki düşüncelerinizi paylaşmanın zamanı geldi. Tanıklığınızı bu [bağlantıda](https://www.asabeneh.com/testimonials) bırakabilirsiniz.
## Egzersizler
### Egzersizler: Seviye 1
1. Koşullu render (conditional rendering) nedir?
2. Koşullu render'ı nasıl uygularsınız?
3. Koşullu render için hangi yöntemi kullanmayı tercih edersiniz?
### Egzersizler: Seviye 2
1. Yılın mevsimine göre (Sonbahar, Kış, İlkbahar, Yaz) arka plan rengini değiştiren tek sayfalık bir uygulama yapın.
2. Günün saatine göre (Sabah, Öğle, Akşam, Gece) arka plan rengini değiştiren tek sayfalık bir uygulama yapın.
### Egzersizler: Seviye 3
1. Veri çekmek belirli bir süre alır. Veri yüklenene kadar kullanıcı beklemek zorundadır. Veri henüz çekilmemişken bir yükleme (loading) fonksiyonelliği uygulayın. Gecikmeyi setTimeout kullanarak simüle edebilirsiniz.
🎉 TEBRİKLER! 🎉
[<< Gün 8](../08_Gun_State/08_state.md) | [Gün 10 >>](../10_Gun_Proje_Klasor_Yapisi/10_proje_klasor_yapisi.md)

@ -0,0 +1,627 @@
<div align="center">
<h1> 30 Days Of React: React Proje Klasör Yapısı (Project Folder Structure)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 9](../09_Gun_Kosullu_Render/09_kosullu_render.md) | [Gün 11 >>](../11_Gun_Olaylar/11_olaylar.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_10.jpg)
- [React Proje Klasör Yapısı ve Dosya İsimlendirme](#react-proje-klasör-yapısı-ve-dosya-i̇simlendirme)
- [Dosya İsimlendirme](#dosya-i̇simlendirme)
- [Klasör](#klasör)
- [Components (Bileşenler) Klasörü](#components-bileşenler-klasörü)
- [Fragment (Parça)](#fragment-parça)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# React Proje Klasör Yapısı ve Dosya İsimlendirme
React projesinde tek bir klasör yapısı ya da dosya isimlendirmesi kullanmanın zorunlu bir yolu yoktur. Çoğu zaman bu tür seçimler bir ekip tarafından yapılabilir. Bazen bir şirketin hangi kod kurallarının, klasör yapısının ve dosya isimlendirmesinin kullanılacağına dair geliştirilmiş yönergeleri olabilir. React projesini yapılandırmanın doğru ya da yanlış yolu yoktur; ancak bazı yapılar ölçeklenebilirlik, sürdürülebilirlik, dosyalar üzerinde çalışma kolaylığı ve anlaşılması kolay yapıısından diğerlerinden daha iyidir. Klasör yapısı hakkında daha fazla bilgi edinmek isterseniz aşağıdaki makaleleri inceleyebilirsiniz:
- [React Folder Structure by https://www.devaradise.com ](https://www.devaradise.com/react-project-folder-structure)
- [React Folder Structure by www.robinwieruch.de ](https://www.robinwieruch.de/react-folder-structure)
- [React Folder Structure by Faraz Ahmad](https://dev.to/farazamiruddin/an-opinionated-guide-to-react-folder-structure-file-naming-1l7i)
- [React Folder Structure by https://maxrozen.com/](https://maxrozen.com/guidelines-improve-react-app-folder-structure/)
Farklı kuralların bir karışımını kullanıyorum. Dilerseniz bunu takip edebilirsiniz; ancak lütfen sizin için anlamlı olan bir yapıya sadık kalın.
## Dosya İsimlendirme
Tüm React projelerimde, tüm component'ler için CamelCase (deve harfi) dosya adı kullanacağım. Açıklayıcı ve uzun isimler kullanmayı tercih ederim.
## Klasör
Tüm görselleri, ikonları ve fontları assets klasöründe, tüm CSS stil dosyalarını ise styles klasöründe toplamayı kolay buluyorum. Tüm component'ler components klasöründe olacak.
Şimdiye kadar index.js dosyası üzerinde çalışıyorduk. index.js'de çok sayıda component bulunuyor. Bugün her component'i ayrı bir dosyaya taşıyacağız ve tüm dosyaları App.js'e import edeceğiz. Bu süreçte klasör yapımı göreceksiniz. Şu anda src dizinindeyiz. Tüm klasör yapısı src dizininin içinde olacak. index.js dosyasından başlayalım. index.js dosyasına ek olarak, bir App.js dosyası oluşturalım ve şimdilik sahip olduğumuz component'lerin çoğunu App.js'e taşıyalım. index.js, component'i index.html ile bağlayan ana kapınızdır.
```js
// src/index.js
// index.js
import React from "react";
import ReactDOM from "react-dom";
const App = () => <h1>Welcome to 30 Days Of React</h1>;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Yukarıdaki kod parçasında App component'i bulunmaktadır. App component'ini kendi dosyasına, App.js'e taşıyalım:
```js
// src/App.js
import React from "react";
const App = () => <h1>Welcome to 30 Days Of React</h1>;
```
Component'i başka bir dosyaya import etmek için dışa aktarmamız (export etmemiz) gerekiyor. Default veya named (isimli) export olarak dışa aktarabiliriz. Bir dosyada bir default export ve çok sayıda named export yapılabilir. Önce named export ile uygulayalım, ardından default export'a geçelim.
Named export yapmak için _let_ veya _const_'tan önce sadece _export_ anahtar kelimesini ekleriz:
```js
// src/App.js
import React from "react";
// ok fonksiyonunda named export
export const App = () => <h1>Welcome to 30 Days Of React</h1>;
```
Normal fonksiyon tanımlamasında dışa aktarma:
```js
// src/App.js
import React from "react";
// normal fonksiyonda named export, function declaration
export function App() {
return <h1>Welcome to 30 Days Of React</h1>;
}
```
Şimdi App component'ini App.js dosyasından index.js dosyasına import edelim:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Named export'u gördük; şimdi default export ile uygulayalım. Bunu iki şekilde yapabiliriz; ancak component'leri dışa aktarırken ikinci yöntem önerilir; çünkü bazen bir component'i başka bir higher order component (yüksek dereceli bileşen) ile sarmalayabiliriz:
```js
// src/App.js
import React from "react";
// ok fonksiyonunda default export
const App = () => <h1>Welcome to 30 Days Of React</h1>;
export default App;
```
```js
// src/App.js
import React from "react";
// default export, normal fonksiyon
export default function App() {
return <h1>Welcome to 30 Days Of React</h1>;
}
```
```js
// src/App.js
// Çoğu durumda önerilen yöntem
import React from "react";
const App = () => <h1>Welcome to 30 Days Of React</h1>;
export default App;
```
Bir component default olarak dışa aktarılmışsa import ederken süslü paranteze gerek yoktur:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
Şimdiye kadar oluşturduğumuz component'leri hatırlarsanız, hepsini bir arada tutuyorduk. Bu şekilde çalışmak kolay değildir. Şimdi tüm component'leri ayrı bir dosyaya taşıyacağız:
```js
// index.js
import React from "react";
import ReactDOM from "react-dom";
import asabenehImage from "./images";
import { countriesData } from "./data/countries";
// Header component (Bileşeni)
class Header extends React.Component {
render() {
console.log(this.props.data);
const {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
} = this.props.data;
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
}
}
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
const formatedCapital =
capital.length > 0 ? (
<>
<span>Capital: </span>
{capital}
</>
) : (
""
);
const formatLanguage = languages.length > 1 ? `Languages` : `Language`;
return (
<div className="country">
<div className="country_flag">
<img src={flag} alt={name} />
</div>
<h3 className="country_name">{name.toUpperCase()}</h3>
<div className="country_text">
<p>{formatedCapital}</p>
<p>
<span>{formatLanguage}: </span>
{languages.join(", ")}
</p>
<p>
<span>Population: </span>
{population.toLocaleString()}
</p>
<p>
<span>Currency: </span>
{currency}
</p>
</div>
</div>
);
};
// User Card Component (Bileşeni)
const UserCard = () => (
<div className="user-card">
<img src={asabenehImage} alt="asabeneh image" />
<h2>Asabeneh Yetayeh</h2>
</div>
);
// Onaltılık (hexadecimal) renk üreteci
const hexaColor = () => {
let str = "0123456789abcdef";
let color = "";
for (let i = 0; i < 6; i++) {
let index = Math.floor(Math.random() * str.length);
color += str[index];
}
return "#" + color;
};
const HexaColor = () => <div>{hexaColor()}</div>;
const Message = ({ message }) => (
<div>
<h1>{message}</h1>
</div>
);
const Login = () => (
<div>
<h3>Please Login</h3>
</div>
);
const Welcome = (props) => (
<div>
<h1>Welcome to 30 Days Of React</h1>
</div>
);
// Düğme component'i
const Button = ({ text, onClick, style }) => (
<button style={style} onClick={onClick}>
{text}
</button>
);
// TechList Component (Bileşeni)
// class tabanlı component
class TechList extends React.Component {
render() {
const { techs } = this.props;
const techsFormatted = techs.map((tech) => <li key={tech}>{tech}</li>);
return techsFormatted;
}
}
// Main Component (Bileşeni)
// Class Component
class Main extends React.Component {
render() {
const { techs, greetPeople, handleTime, loggedIn, handleLogin, message } =
this.props;
console.log(message);
const status = loggedIn ? <Welcome /> : <Login />;
return (
<main>
<div className="main-wrapper">
<p>Prerequisite to get started react.js:</p>
<ul>
<TechList techs={this.props.techs} />
</ul>
{techs.length === 3 && (
<p>You have all the prerequisite courses to get started React</p>
)}
<div>
<Button
text="Show Time"
onClick={handleTime}
style={buttonStyles}
/>{" "}
<Button
text="Greet People"
onClick={greetPeople}
style={buttonStyles}
/>
{!loggedIn && (
<p>
Please login to access more information about 30 Days Of React
challenge
</p>
)}
</div>
<div style={{ margin: 30 }}>
<Button
text={loggedIn ? "Logout" : "Login"}
style={buttonStyles}
onClick={handleLogin}
/>
<br />
{status}
</div>
<Message message={message} />
</div>
</main>
);
}
}
// CSS stilleri JavaScript nesnesi olarak
const buttonStyles = {
backgroundColor: "#61dbfb",
padding: 10,
border: "none",
borderRadius: 5,
margin: 3,
cursor: "pointer",
fontSize: 22,
color: "white",
margin: "0 auto",
};
// Footer Component (Bileşeni)
// Class component
class Footer extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<footer>
<div className="footer-wrapper">
<p>Copyright {this.props.date.getFullYear()}</p>
</div>
</footer>
);
}
}
class App extends React.Component {
state = {
loggedIn: false,
techs: ["HTML", "CSS", "JS"],
message: "Click show time or Greet people to change me",
};
handleLogin = () => {
this.setState({
loggedIn: !this.state.loggedIn,
});
};
showDate = (time) => {
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const month = months[time.getMonth()].slice(0, 3);
const year = time.getFullYear();
const date = time.getDate();
return `${month} ${date}, ${year}`;
};
handleTime = () => {
let message = this.showDate(new Date());
this.setState({ message });
};
greetPeople = () => {
let message = "Welcome to 30 Days Of React Challenge, 2020";
this.setState({ message });
};
render() {
const data = {
welcome: "30 Days Of React",
title: "Getting Started React",
subtitle: "JavaScript Library",
author: {
firstName: "Asabeneh",
lastName: "Yetayeh",
},
date: "Oct 9, 2020",
};
const techs = ["HTML", "CSS", "JavaScript"];
return (
<div className="app">
<Header data={data} />
<Main
techs={techs}
handleTime={this.handleTime}
greetPeople={this.greetPeople}
loggedIn={this.state.loggedIn}
handleLogin={this.handleLogin}
message={this.state.message}
/>
<Footer date={new Date()} />
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```
## Components (Bileşenler) Klasörü
src dizininin içinde tüm component'leri ayrı bir klasörde toplayacağız:
```sh
src
App.js
index.js
components
-auth
-Signup.js
-Signin.js
-ForgotPassword.js
-ResetPassword.js
header
-Header.js
footer
-Footer.js
assets
-images
-icons
-fonts
styles
-button.js
-button.scss
utils
-random-id.js
-display-time.js
-generate-color.js
shared
-Button.js
-InputField.js
-TextAreaField.js
```
src içinde components dizini oluşturalım; components içinde header dizini oluşturalım. header dizini içinde Header.js dosyası oluşturalım:
```js
// src/components/header/Header.js
import React from "react";
const Header = ({
data: {
welcome,
title,
subtitle,
author: { firstName, lastName },
date,
},
}) => {
return (
<header>
<div className="header-wrapper">
<h1>{welcome}</h1>
<h2>{title}</h2>
<h3>{subtitle}</h3>
<p>
{firstName} {lastName}
</p>
<small>{date}</small>
</div>
</header>
);
};
export default Header;
```
Header'a benzer şekilde, tüm component'leri ilgili dosyalarına taşıyalım. index.html'deki tüm CSS dosyaları styles klasörüne taşınacak; her parça kendi dosyasına ayrıldıktan sonra styles klasörünü kontrol etmeye çalışın.
## Fragment (Parça)
Fragment'lar (Parçalar), JSX'te gereksiz üst element kullanmaktan kaçınmanın bir yoludur. Bir fragment uygulayalım. Fragment'ı react modülünden import ediyoruz. Aşağıda görüldüğü gibi React ve fragment'ı virgül ayırımı kullanarak birlikte import ettik:
```js
import React, { Fragment } from "react";
const Skills = () => {
return (
<Fragment>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</Fragment>
);
};
const RequiredSkills = () => {
return (
<ul>
<Skills />
</ul>
);
};
```
Fragment modülünü React'tan şu şekilde çıkarmak da mümkündür:
```js
import React from "react";
const Skills = () => {
return (
<React.Fragment>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</React.Fragment>
);
};
const RequiredSkills = () => {
return (
<ul>
<Skills />
</ul>
);
};
```
React'ın son sürümünde bu işaretler kullanılarak çıkarmadan veya import etmeden de yazılabilir (<> </>):
```js
import React from "react";
// Önerilen yöntem
const Skills = () => {
return (
<>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</>
);
};
const RequiredSkills = () => {
return (
<ul>
<Skills />
</ul>
);
};
```
Class tabanlı component yaparken React.Component kullanıyorduk; bunun yerine sadece Component'i import ederek kodu daha temiz yazabiliriz. Bir örnek görelim:
```js
import React from "react";
// Component'i import etmeden
// Önerilmez
class App extends React.Component {
render() {
return <h1> 30 Days of React </h1>;
}
}
```
```js
import React, { Component } from "react";
// Bu önerilen yöntemdir
class App extends Component {
render() {
return <h1> 30 Days of React </h1>;
}
}
```
Harika iş çıkardınız. Beyniniz ve kaslarınız için bazı egzersizler yapma zamanı.
# Egzersizler
## Egzersizler: Seviye 1
1. React Klasör Yapısı ve Dosya İsimlendirmesinin önemi nedir?
2. Dosya nasıl dışa aktarılır (export edilir)?
3. Dosya nasıl içe aktarılır (import edilir)?
4. Bir component veya modül oluşturun ve named ya da default export ile dışa aktarın.
5. Bir component veya modül oluşturun ve import edin.
6. Sahip olduğunuz tüm component'leri farklı bir klasör yapısına taşıyın.
## Egzersizler: Seviye 2
1. Şimdiye kadar oluşturduğumuz component'leri kullanarak basit bir portföy yapın. 8. gün meydan okumasında yazdığımız fonksiyonu kullanarak karanlık mod (dark mode) uygulayın.
## Egzersizler: Seviye 3
Yakında
🎉 TEBRİKLER! 🎉
[<< Gün 9](../09_Gun_Kosullu_Render/09_kosullu_render.md) | [Gün 11 >>](../11_Gun_Olaylar/11_olaylar.md)

@ -0,0 +1,239 @@
<div align="center">
<h1> 30 Days Of React: Olaylar (Events)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 10](../10_Gun_Proje_Klasor_Yapisi/10_proje_klasor_yapisi.md) | [Gün 12 >>](../12_Gun_Formlar/12_formlar.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_8.jpg)
- [Olaylar (Events)](#olaylar-events)
- [Olay (Event) Nedir?](#olay-event-nedir)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Olaylar (Events)
## Olay (Event) Nedir?
Bir olay (event), bir yazılım tarafından tanınan bir eylem veya oluşumdur. Olayı daha iyi anlamak için bilgisayar kullanırken yaptığımız günlük aktiviteleri düşünebiliriz: bir düğmeye tıklamak, bir görsel üzerinde fareyi gezdirmek, klavyeye basmak, fare tekerleğini kaydırmak vb. Bu bölümde yalnızca bazı fare ve klavye olaylarına odaklanacağız. React belgeleri [events (olaylar)](https://reactjs.org/docs/handling-events.html) hakkında zaten ayrıntılı bir not içermektedir.
React'te olay yönetimi (event handling), saf JavaScript kullanarak DOM öğeleri üzerindeki olay yönetimine çok benzer. React'te olay yönetimi ile saf JavaScript arasındaki bazı sözdizimi farklılıkları şunlardır:
- React olayları, küçük harf yerine camelCase kullanılarak isimlendirilir.
- JSX ile olay işleyiciye (event handler) bir string yerine bir fonksiyon geçirilir.
Olay yönetimini anlamak için bazı örneklere bakalım.
HTML'de olay yönetimi:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>30 Days Of React App</title>
</head>
<body>
<button>onclick="insanlariSelamla()">İnsanları Selamla</button>
<script>
const insanlariSelamla = () => {
alert('30 Günde React Meydan Okumasına Hoş Geldiniz')
}
</script>
</body>
</html>
```
React'te ise biraz farklıdır:
```js
import React from 'react'
// fonksiyonel component ise
const App = () => {
const insanlariSelamla = () => {
alert('30 Günde React Meydan Okumasına Hoş Geldiniz')
}
return <button onClick={insanlariSelamla}> </button>
}
```
```js
import React, { Component } from 'react'
// fonksiyonel component ise
class App extends Component {
insanlariSelamla = () => {
alert('30 Günde React Meydan Okumasına Hoş Geldiniz')
}
render() {
return <button onClick={this.insanlariSelamla}> </button>
}
}
```
HTML ve React olayları arasındaki bir diğer fark, React'te varsayılan davranışı engellemek için `false` döndürememenizdir. `preventDefault`'u açıkça çağırmanız gerekir. Örneğin, saf HTML'de yeni bir sayfanın açılmasını engellemek için şunlar yazılabilir:
Saf HTML:
```html
<a href="#" onclick="console.log('Bağlantıya tıklandı.'); return false">
Bana tıkla
</a>
```
Ancak React'te şu şekilde olabilir:
```js
import React, { Component } from 'react'
// fonksiyonel component ise
class App extends Component {
handleClick = () => {
alert('30 Günde React Meydan Okumasına Hoş Geldiniz')
}
render() {
return (
<a href='#' onClick={this.handleClick}>
Bana tıkla
</a>
)
}
}
```
Olay yönetimi çok geniş bir konudur ve bu meydan okumada en yaygın olay türlerine odaklanacağız. Aşağıdaki fare ve klavye olaylarını kullanabiliriz:
_onMouseMove, onMouseEnter, onMouseLeave, onMouseOut, onClick, onKeyDown, onKeyPress, onKeyUp, onCopy, onCut, onDrag, onChange, onBlur, onInput, onSubmit_
Birkaç fare ve klavye olayını daha uygulayalım:
```js
// index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
state = {
firstName: '',
message: '',
key: '',
}
handleClick = (e) => {
// e bir olay nesnesi verir
// e'nin değerini console.log(e) ile kontrol edin
this.setState({
message: 'Olaylar dünyasına hoş geldiniz',
})
}
// fare her hareket ettiğinde tetiklenir
handleMouseMove = (e) => {
this.setState({ message: 'fare hareket ediyor' })
}
// input alanı değer değiştirdiğinde değeri almak için
handleChange = (e) => {
this.setState({
firstName: e.target.value,
message: e.target.value,
})
}
// input alanına basıldığında klavye tuş kodunu almak için
// input ve textarea ile çalışır
handleKeyPress = (e) => {
this.setState({
message:
`${e.target.value} tuşuna basıldı ve tuş kodu: ` + e.charCode,
})
}
// Blur, fare bir input alanından ayrıldığında gerçekleşir
handleBlur = (e) => {
this.setState({ message: 'Input alanı odak kaybetti (blur)' })
}
// Bu olay bir metin kopyalama sırasında tetiklenir
handleCopy = (e) => {
this.setState({
message: '30 Günde React\'i ticari amaçlarla kullanmak yasaktır',
})
}
render() {
return (
<div>
<h1>Olaylar Dünyasına Hoş Geldiniz</h1>
<button onClick={this.handleClick}>Bana Tıkla</button>
<button onMouseMove={this.handleMouseMove}>Fareyi üzerime getir</button>
<p onCopy={this.handleCopy}>
Bu metni kopyalayarak telif hakkı iznini kontrol edin
</p>
<p>{this.state.message}</p>
<label htmlFor=''> onKeyPress Olayı Testi: </label>
<input type='text' onKeyPress={this.handleKeyPress} />
<br />
<label htmlFor=''> onBlur Olayı Testi: </label>
<input type='text' onBlur={this.handleBlur} />
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor='firstName'>Ad: </label>
<input
onChange={this.handleChange}
name='firstName'
value={this.state.value}
/>
</div>
<div>
<input type='submit' value='Gönder' />
</div>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
// JSX öğesini ReactDOM paketi ile render ediyoruz
ReactDOM.render(<App />, rootElement)
```
# Egzersizler
## Egzersizler: Seviye 1
1. Olay (event) nedir?
2. HTML öğe olayı ile React olayı arasındaki fark nedir?
3. En az 4 klavye olayı yazın.
4. En az 8 fare olayı yazın.
5. En yaygın fare ve klavye olayları nelerdir?
6. Input öğesine özgü bir olay yazın.
7. Form öğesine özgü bir olay yazın.
8. Body üzerinde fare hareket ederken görüntü alanının (viewport) koordinatlarını gösterin.
9. onInput, onChange ve onBlur arasındaki fark nedir?
10. onSubmit olayı nereye yerleştirilir?
## Egzersizler: Seviye 2
Aşağıdakini onMouseEnter olayını kullanarak uygulayın:
![onMouseEnter olayı](../../images/react_event_on_mouse_enter.gif)
## Egzersizler: Seviye 3
Yakında
🎉 TEBRİKLER! 🎉
[<< Gün 10](../10_Gun_Proje_Klasor_Yapisi/10_proje_klasor_yapisi.md) | [Gün 12 >>](../12_Gun_Formlar/12_formlar.md)

@ -0,0 +1,949 @@
<div align="center">
<h1> 30 Days Of React: Formlar (Forms)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 11](../11_Gun_Olaylar/11_olaylar.md) | [Gün 13 >>](../13_Gun_Kontrollü_ve_Kontrolsüz_Input/13_kontrolsuz_input.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_12.jpg)
- [Formlar (Forms)](#formlar-forms)
- [Input Alanından Veri Almak](#input-alanından-veri-almak)
- [Formdan Birden Fazla Input Verisi Almak](#formdan-birden-fazla-input-verisi-almak)
- [Farklı Input Alan Türlerinden Veri Almak](#farklı-input-alan-türlerinden-veri-almak)
- [Form Doğrulama (Validation)](#form-doğrulama-validation)
- [Doğrulama Nedir?](#doğrulama-nedir)
- [Doğrulamanın Amacı Nedir?](#doğrulamanın-amacı-nedir)
- [Doğrulama Türleri](#doğrulama-türleri)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Formlar (Forms)
Form, kullanıcıdan veri toplamak için kullanılır. Zaman zaman bir kâğıt üzerinde ya da bir web sitesinde bilgilerimizi doldurmak için form kullanırız. Kayıt olmak, giriş yapmak veya bir işe başvurmak için farklı form alanlarını doldurarak verilerimizi uzak bir veritabanına göndeririz. Bir formu doldururken basit metin, e-posta, parola, telefon, tarih, onay kutusu (checkbox), radyo düğmesi, seçim kutusu ve metin alanı gibi farklı form alanlarıyla karşılaşırız. HTML5, oldukça fazla alan türü sunmaktadır. Aşağıdaki mevcut HTML5 input türlerine göz atabilirsiniz.
```html
<input type="text" />
<input type="number" />
<input type="range" />
<input type="email" />
<input type="password" />
<input type="tel" />
<input type="checkbox" />
<input type="radio" />
<input type="color" />
<input type="url" />
<input type="image" />
<input type="file" />
<input type="hidden" />
<input type="date" />
<input type="datetime-local" />
<input type="month" />
<input type="week" />
<input type="time" />
<input type="reset" />
<input type="search" />
<input type="submit" />
<input type="button" />
```
Formdan veri almak için kullanılan diğer HTML alanları arasında textarea ve seçenekli select öğesi yer alır.
```html
<textarea>Lütfen yorumunuzu yazın ...</textarea>
<select name="country">
<option value="">Ülkenizi seçin</option>
<option value="finland">Finlandiya</option>
<option value="sweden">İsveç</option>
<option value="denmark">Danimarka</option>
<option value="norway">Norveç</option>
<option value="iceland">İzlanda</option>
</select>
```
Artık bir formdan veri almak için ihtiyaç duyduğumuz alanların çoğunu biliyorsunuz. Metin tipinde bir input ile başlayalım. Bir önceki günde farklı olay türlerini gördük; bugün ise bir input alanının verisi değiştiğinde tetiklenen _onChange_ olay türüne odaklanacağız. Input alanı varsayılan olarak girilen veriyi hafızada tutar; ancak bu bölümde bunu state kullanarak kontrol edecek ve kontrollü (controlled) bir input uygulayacağız. Kontrolsüz (uncontrolled) input'u ayrı bir bölümde ele alacağız.
## Input Alanından Veri Almak
Şimdiye kadar input alanından herhangi bir veri almadık. Şimdi bir input alanından nasıl veri alacağımızı öğrenme zamanı. Kontrollü bir input'tan veri alabilmek için bir input alanına, olay dinleyicisine (onChange) ve state'e ihtiyacımız var. Aşağıdaki örneğe bakın. Input etiketinin altındaki h1 öğesi, input'a yazdığımız şeyi gösterir. Canlı [demo](https://codepen.io/Asabeneh/full/OJVpyqm)'ya bakabilirsiniz.
Input öğesinin value, name, id, placeholder, type ve olay işleyicisi gibi birçok niteliği (attribute) vardır. Buna ek olarak, bir label ile input alanını input alanının id'si ve etiketin htmlFor'u aracılığıyla ilişkilendirebiliriz. Label ve input ilişkilendirildiğinde, etikete tıklandığında input'a odaklanır. Aşağıdaki örneğe bakın.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
// state tanımlama
// başlangıç state'i
state = {
firstName: '',
}
handleChange = (e) => {
const value = e.target.value
this.setState({ firstName: value })
}
render() {
/*
state değerine erişim ve
bu değer input'un value niteliğine enjekte edilecek
*/
const firstName = this.state.firstName
return (
<div className='App'>
<label htmlFor='firstName'>Ad: </label>
<input
type='text'
id='firstName'
name='firstName'
placeholder='Ad'
value={firstName}
onChange={this.handleChange}
/>
<h1>{this.state.firstName}</h1>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Kullanıcı bilgilerini yönetmek için genellikle form kullanırız. Form bölümüne geçerek form öğesini kullanalım.
## Formdan Birden Fazla Input Verisi Almak
Bu bölümde kullanıcı bilgilerini toplayan küçük bir form geliştireceğiz. Kullanıcımız bir öğrencidir. Kullanıcı bilgilerini toplamak için üst (parent) bir form öğesi ve belirli sayıda input öğesi kullanacağız. Bunlara ek olarak form için (onSubmit) ve input'lar için (onChange) olay dinleyicilerimiz olacak. Aşağıdaki örneğe bakın, yorumları da incelemeye çalışın. Canlı [demo](https://codepen.io/Asabeneh/full/eYNvJda)'ya da bakabilirsiniz.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
// başlangıç state'ini tanımlama
state = {
firstName: '',
lastName: '',
country: '',
title: '',
}
handleChange = (e) => {
/*
name ve value'yu şu şekilde alabiliriz: e.target.name, e.target.value
ya da e.target'tan name ve value'yu destructure edebiliriz
const name = e.target.name
const value = e.target.value
*/
const { name, value } = e.target
// bir nesnede anahtar olarak değişken adı kullanmak için [değişkenadı]
// name, input öğelerinin name niteliğine atıfta bulunur
this.setState({ [name]: value })
}
handleSubmit = (e) => {
/*
e.preventDefault()
form öğesinin varsayılan davranışını durdurur
özellikle sayfanın yenilenmesini engeller
*/
e.preventDefault()
/*
burası backend api'ye bağlandığımız ve
verinin veritabanına gönderildiği yerdir
*/
console.log(this.state)
}
render() {
// state'i destructure ederek state değerine erişim
const { firstName, lastName, title, country } = this.state
return (
<div className='App'>
<h3>Öğrenci Ekle</h3>
<form onSubmit={this.handleSubmit}>
<div>
<input
type='text'
name='firstName'
placeholder='Ad'
value={firstName}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='lastName'
placeholder='Soyad'
value={lastName}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='country'
placeholder='Ülke'
value={country}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='title'
placeholder='Ünvan'
value={title}
onChange={this.handleChange}
/>
</div>
<button class='btn btn-success'>Gönder</button>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Yukarıdaki form yalnızca metin türlerini işlemektedir, ancak farklı input alanı türleri de mevcuttur. Tüm farklı input alanı türlerini işleyen başka bir form yapalım.
## Farklı Input Alan Türlerinden Veri Almak
```js
// index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const options = [
{
value: '',
label: '-- Ülke Seçin --',
},
{
value: 'Finland',
label: 'Finlandiya',
},
{
value: 'Sweden',
label: 'İsveç',
},
{
value: 'Norway',
label: 'Norveç',
},
{
value: 'Denmark',
label: 'Danimarka',
},
]
// seçenekleri JSX option listesine (dizisine) eşleme
const selectOptions = options.map(({ value, label }) => (
<option value={value}> {label}</option>
))
class App extends React.Component {
// state tanımlama
state = {
firstName: '',
lastName: '',
email: '',
country: '',
tel: '',
dateOfBirth: '',
favoriteColor: '',
weight: '',
gender: '',
file: '',
bio: '',
skills: {
html: false,
css: false,
javascript: false,
},
}
handleChange = (e) => {
/*
name ve value'yu şu şekilde alabiliriz: e.target.name, e.target.value
ya da e.target'tan name ve value'yu destructure edebiliriz
const name = e.target.name
const value = e.target.value
*/
const { name, value, type, checked } = e.target
/*
[değişkenadı] — belirli bir değişkende saklanan değeri nesne için anahtar olarak kullanabiliriz; bu durumda state için bir anahtar
*/
if (type === 'checkbox') {
this.setState({
skills: { ...this.state.skills, [name]: checked },
})
} else if (type === 'file') {
console.log(type, 'buraya bakın')
this.setState({ [name]: e.target.files[0] })
} else {
this.setState({ [name]: value })
}
}
handleSubmit = (e) => {
/*
e.preventDefault()
form öğesinin varsayılan davranışını durdurur
özellikle sayfanın yenilenmesini engeller
*/
e.preventDefault()
const {
firstName,
lastName,
email,
tel,
dateOfBirth,
favoriteColor,
weight,
country,
gender,
bio,
file,
skills,
} = this.state
const formattedSkills = []
for (const key in skills) {
console.log(key)
if (skills[key]) {
formattedSkills.push(key.toUpperCase())
}
}
const data = {
firstName,
lastName,
email,
tel,
dateOfBirth,
favoriteColor,
weight,
country,
gender,
bio,
file,
skills: formattedSkills,
}
/*
burası backend api'ye bağlandığımız ve
verinin veritabanına gönderildiği yerdir
*/
console.log(data)
}
render() {
// state'i destructure ederek state değerine erişim
const {
firstName,
lastName,
email,
tel,
dateOfBirth,
favoriteColor,
weight,
country,
gender,
bio,
} = this.state
return (
<div className='App'>
<h3>Öğrenci Ekle</h3>
<form onSubmit={this.handleSubmit}>
<div className='row'>
<div className='form-group'>
<label htmlFor='firstName'>Ad </label>
<input
type='text'
name='firstName'
value={firstName}
onChange={this.handleChange}
placeholder='Ad'
/>
</div>
<div className='form-group'>
<label htmlFor='lastName'>Soyad </label>
<input
type='text'
name='lastName'
value={this.state.lastName}
onChange={this.handleChange}
placeholder='Soyad'
/>
</div>
<div className='form-group'>
<label htmlFor='email'>E-posta </label>
<input
type='email'
name='email'
value={email}
onChange={this.handleChange}
placeholder='E-posta'
/>
</div>
</div>
<div className='form-group'>
<label htmlFor='tel'>Telefon </label>
<input
type='tel'
name='tel'
value={tel}
onChange={this.handleChange}
placeholder='Tel'
/>
</div>
<div className='form-group'>
<label htmlFor='dateOfBirth'>Doğum tarihi </label>
<input
type='date'
name='dateOfBirth'
value={dateOfBirth}
onChange={this.handleChange}
placeholder='Doğum Tarihi'
/>
</div>
<div className='form-group'>
<label htmlFor='favoriteColor'>En Sevdiğiniz Renk</label>
<input
type='color'
id='color'
name='color'
value={favoriteColor}
onChange={this.handleChange}
placeholder='En Sevdiğiniz Renk'
/>
</div>
<div className='form-group'>
<label htmlFor='weight'>Kilo </label>
<input
type='number'
id='weight'
name='weight'
value={weight}
onChange={this.handleChange}
placeholder='Kg cinsinden kilo'
/>
</div>
<div>
<label htmlFor='country'>Ülke</label> <br />
<select name='country' onChange={this.handleChange} id='country'>
{selectOptions}
</select>
</div>
<div>
<p>Cinsiyet</p>
<div>
<input
type='radio'
id='female'
name='gender'
value='Female'
onChange={this.handleChange}
checked={gender === 'Female'}
/>
<label htmlFor='female'>Kadın</label>
</div>
<div>
<input
id='male'
type='radio'
name='gender'
value='Male'
onChange={this.handleChange}
checked={gender === 'Male'}
/>
<label htmlFor='male'>Erkek</label>
</div>
<div>
<input
id='other'
type='radio'
name='gender'
value='Other'
onChange={this.handleChange}
checked={gender === 'Other'}
/>
<label htmlFor='other'>Diğer</label>
</div>
</div>
<div>
<p>Becerilerinizi seçin</p>
<div>
<input
type='checkbox'
id='html'
name='html'
onChange={this.handleChange}
/>
<label htmlFor='html'>HTML</label>
</div>
<div>
<input
type='checkbox'
id='css'
name='css'
onChange={this.handleChange}
/>
<label htmlFor='css'>CSS</label>
</div>
<div>
<input
type='checkbox'
id='javascript'
name='javascript'
onChange={this.handleChange}
/>
<label htmlFor='javascript'>JavaScript</label>
</div>
</div>
<div>
<label htmlFor='bio'>Biyografi</label> <br />
<textarea
id='bio'
name='bio'
value={bio}
onChange={this.handleChange}
cols='120'
rows='10'
placeholder='Kendinizden bahsedin ...'
/>
</div>
<div>
<input type='file' name='file' onChange={this.handleChange} />
</div>
<div>
<button>Gönder</button>
</div>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
## Form Doğrulama (Validation)
## Doğrulama Nedir?
Doğrulama, bu durumda verinin geçerliliğini veya doğruluğunu kontrol etme ya da kanıtlama eylemi veya sürecidir.
## Doğrulamanın Amacı Nedir?
Doğrulamanın temel amacı, kullanıcılardan istenen veriyi elde etmektir. Bunun yanı sıra kötü niyetli kullanıcıları ve verileri engellemek amacıyla da kullanılır.
## Doğrulama Türleri
Doğrulama, istemci tarafında (client side) veya sunucu tarafında (server side) yapılabilir. Şu anda bir ön yüz teknolojisi olan React kullanıyoruz ve istemci tarafı doğrulaması uyguluyoruz. Doğrulama, HTML5'in yerleşik doğrulaması kullanılarak veya JavaScript (düzenli ifadeler / regular expression) kullanılarak uygulanabilir.
Aşağıdaki kod parçasında ilk alana bir doğrulama uygulanmıştır. Nasıl çalıştığını anlamaya çalışın. Input odaklanılmadığında geçerliliği kontrol etmek için onBlur olayı kullanılmıştır.
```js
// index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const options = [
{
value: '',
label: '-- Ülke Seçin --',
},
{
value: 'Finland',
label: 'Finlandiya',
},
{
value: 'Sweden',
label: 'İsveç',
},
{
value: 'Norway',
label: 'Norveç',
},
{
value: 'Denmark',
label: 'Danimarka',
},
]
// seçenekleri JSX option listesine (dizisine) eşleme
const selectOptions = options.map(({ value, label }) => (
<option value={value}> {label}</option>
))
class App extends Component {
// state tanımlama
state = {
firstName: '',
lastName: '',
email: '',
country: '',
tel: '',
dateOfBirth: '',
favoriteColor: '',
weight: '',
gender: '',
file: '',
bio: '',
skills: {
html: false,
css: false,
javascript: false,
},
touched: {
firstName: false,
lastName: false,
},
}
handleChange = (e) => {
/*
name ve value'yu şu şekilde alabiliriz: e.target.name, e.target.value
ya da e.target'tan name ve value'yu destructure edebiliriz
const name = e.target.name
const value = e.target.value
*/
const { name, value, type, checked } = e.target
/*
[değişkenadı] — belirli bir değişkende saklanan değeri nesne için anahtar olarak kullanabiliriz; bu durumda state için bir anahtar
*/
if (type === 'checkbox') {
this.setState({
skills: { ...this.state.skills, [name]: checked },
})
} else if (type === 'file') {
this.setState({ [name]: e.target.files[0] })
} else {
this.setState({ [name]: value })
}
}
handleBlur = (e) => {
const { name, value } = e.target
this.setState({ touched: { ...this.state.touched, [name]: true } })
}
validate = () => {
// Hata geri bildirimlerini toplamak ve formda göstermek için nesne
const errors = {
firstName: '',
}
if (
(this.state.touched.firstName && this.state.firstName.length < 3) ||
(this.state.touched.firstName && this.state.firstName.length > 12)
) {
errors.firstName = 'Ad 2 ile 12 karakter arasında olmalıdır'
}
return errors
}
handleSubmit = (e) => {
/*
e.preventDefault()
form öğesinin varsayılan davranışını durdurur
özellikle sayfanın yenilenmesini engeller
*/
e.preventDefault()
const {
firstName,
lastName,
email,
country,
gender,
tel,
dateOfBirth,
favoriteColor,
weight,
bio,
file,
skills,
} = this.state
const formattedSkills = []
for (const key in skills) {
console.log(key)
if (skills[key]) {
formattedSkills.push(key.toUpperCase())
}
}
const data = {
firstName,
lastName,
email,
country,
gender,
tel,
dateOfBirth,
favoriteColor,
weight,
bio,
file,
skills: formattedSkills,
}
/*
burası backend api'ye bağlandığımız ve
verinin veritabanına gönderildiği yerdir
*/
console.log(data)
}
render() {
// state'i destructure ederek state değerine erişim
// formdaki noValidate niteliği HTML5'in yerleşik doğrulamasını devre dışı bırakır
const { firstName } = this.validate()
return (
<div className='App'>
<h3>Öğrenci Ekle</h3>
<form onSubmit={this.handleSubmit} noValidate>
<div className='row'>
<div className='form-group'>
<label htmlFor='firstName'>Ad </label>
<input
type='text'
name='firstName'
value={this.state.firstName}
onChange={this.handleChange}
onBlur={this.handleBlur}
placeholder='Ad'
/> <br />
<small>{firstName}</small>
</div>
<div className='form-group'>
<label htmlFor='lastName'>Soyad </label>
<input
type='text'
name='lastName'
value={this.state.lastName}
onChange={this.handleChange}
placeholder='Soyad'
/>
</div>
<div className='form-group'>
<label htmlFor='email'>E-posta </label>
<input
type='email'
name='email'
value={this.state.email}
onChange={this.handleChange}
placeholder='E-posta'
/>
</div>
</div>
<div className='form-group'>
<label htmlFor='tel'>Telefon </label>
<input
type='tel'
name='tel'
value={this.state.tel}
onChange={this.handleChange}
placeholder='Tel'
/>
</div>
<div className='form-group'>
<label htmlFor='dateOfBirth'>Doğum tarihi </label>
<input
type='date'
name='dateOfBirth'
value={this.state.dateOfBirth}
onChange={this.handleChange}
placeholder='Doğum Tarihi'
/>
</div>
<div className='form-group'>
<label htmlFor='favoriteColor'>En Sevdiğiniz Renk</label>
<input
type='color'
id='favoriteColor'
name='favoriteColor'
value={this.state.favoriteColor}
onChange={this.handleChange}
placeholder='En Sevdiğiniz Renk'
/>
</div>
<div className='form-group'>
<label htmlFor='weight'>Kilo </label>
<input
type='number'
id='weight'
name='weight'
value={this.state.weight}
onChange={this.handleChange}
placeholder='Kg cinsinden kilo'
/>
</div>
<div>
<label htmlFor='country'>Ülke</label> <br />
<select name='country' onChange={this.handleChange} id='country'>
{selectOptions}
</select>
</div>
<div>
<p>Cinsiyet</p>
<div>
<input
type='radio'
id='female'
name='gender'
value='Female'
onChange={this.handleChange}
checked={this.state.gender === 'Female'}
/>
<label htmlFor='female'>Kadın</label>
</div>
<div>
<input
id='male'
type='radio'
name='gender'
value='Male'
onChange={this.handleChange}
checked={this.state.gender === 'Male'}
/>
<label htmlFor='male'>Erkek</label>
</div>
<div>
<input
id='other'
type='radio'
name='gender'
value='Other'
onChange={this.handleChange}
checked={this.state.gender === 'Other'}
/>
<label htmlFor='other'>Diğer</label>
</div>
</div>
<div>
<p>Becerilerinizi seçin</p>
<div>
<input
type='checkbox'
id='html'
name='html'
onChange={this.handleChange}
/>
<label htmlFor='html'>HTML</label>
</div>
<div>
<input
type='checkbox'
id='css'
name='css'
onChange={this.handleChange}
/>
<label htmlFor='css'>CSS</label>
</div>
<div>
<input
type='checkbox'
id='javascript'
name='javascript'
onChange={this.handleChange}
/>
<label htmlFor='javascript'>JavaScript</label>
</div>
</div>
<div>
<label htmlFor='bio'>Biyografi</label> <br />
<textarea
id='bio'
name='bio'
value={this.state.bio}
onChange={this.handleChange}
cols='120'
rows='10'
placeholder='Kendinizden bahsedin ...'
/>
</div>
<div>
<input type='file' name='file' onChange={this.handleChange} />
</div>
<div>
<button>Gönder</button>
</div>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
# Egzersizler
## Egzersizler: Seviye 1
1. Formun önemi nedir?
2. Kaç tane input türü biliyorsunuz?
3. Bir input öğesinin en az dört niteliğini (attribute) belirtin.
4. htmlFor'un önemi nedir?
5. Örnekte verilmemiş bir input türü varsa onu yazın.
6. Kontrollü (controlled) input nedir?
7. Kontrollü bir input yazmak için neye ihtiyaç duyarsınız?
8. Bir input alanındaki değişiklikleri dinlemek için hangi olay türünü kullanırsınız?
9. İşaretlenmiş (checked) bir checkbox'ın değeri nedir?
10. onChange, onBlur, onSubmit'i ne zaman kullanırsınız?
11. Submit işleyici metodunun içine e.preventDefault() yazmanın amacı nedir?
12. React'te veriler nasıl bağlanır (data binding)? İlk input alanı örneği React'te veri bağlamadır.
13. Doğrulama (validation) nedir?
14. Bir input değiştiğinde dinlemek için hangi olay türünü kullanırsınız?
15. Bir input'u doğrulamak için hangi olay türlerini kullanırsınız?
## Egzersizler: Seviye 2
1. Yukarıda verilen formu doğrulayın (daha sonra bir gif görseli veya video sağlanacaktır). Önce herhangi bir kütüphane kullanmadan doğrulamayı deneyin, ardından [validator.js](https://www.npmjs.com/package/validator) ile deneyin.
## Egzersizler: Seviye 3
Yakında ..
🎉 TEBRİKLER! 🎉
[<< Gün 11](../11_Gun_Olaylar/11_olaylar.md) | [Gün 13 >>](../13_Gun_Kontrollü_ve_Kontrolsüz_Input/13_kontrolsuz_input.md)

@ -0,0 +1,177 @@
<div align="center">
<h1> 30 Days Of React: Kontrolsüz Bileşen (Uncontrolled Component)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 12](../12_Gun_Formlar/12_formlar.md) | [Gün 14 >>](../14_Gun_Bilesen_Yasam_Donguleri/14_bilesen_yasam_donguleri.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_13.jpg)
- [Kontrolsüz Bileşenler (Uncontrolled Components)](#kontrolsüz-bileşenler-uncontrolled-components)
- [Kontrolsüz Input'tan Veri Almak](#kontrolsüz-inputtan-veri-almak)
- [Formdan Birden Fazla Input Verisi Almak](#formdan-birden-fazla-input-verisi-almak)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
# Kontrolsüz Bileşenler (Uncontrolled Components)
Bir önceki gün meydan okumada kontrollü (controlled) input'ları ele aldık. React'te çoğu zaman, [React'in resmi belgelerinde](https://reactjs.org/docs/uncontrolled-components.html) önerildiği şekilde kontrollü input'lar kullanılır.
Kontrolsüz bir bileşen yazmak için, her state güncellemesi için bir olay işleyicisi yazmak yerine, DOM'dan form değerlerini almak amacıyla bir ref kullanabilirsiniz. Kontrolsüz input'ta, geleneksel HTML form veri yönetimine benzer şekilde input alanlarından veri alırız.
Kontrolsüz bileşen örneği:
## Kontrolsüz Input'tan Veri Almak
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
firstName = React.createRef()
handleSubmit = (e) => {
e.preventDefault()
console.log(this.firstName.current.value)
}
render() {
return (
<div className='App'>
<form onSubmit={this.handleSubmit}>
<label htmlFor='firstName'>Ad: </label>
<input
type='text'
id='firstName'
name='firstName'
placeholder='Ad'
ref={this.firstName}
/>
<button type='submit'>Gönder</button>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
## Formdan Birden Fazla Input Verisi Almak
DOM'dan birden fazla input verisi alabiliriz. DOM'u doğrudan hedeflemiyoruz; React, ref kullanarak DOM'dan veri alıyor.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
firstName = React.createRef()
lastName = React.createRef()
country = React.createRef()
title = React.createRef()
handleSubmit = (e) => {
// form öğesinin varsayılan davranışını, özellikle sayfanın yenilenmesini durdurur
e.preventDefault()
console.log(this.firstName.current.value)
console.log(this.lastName.current.value)
console.log(this.title.current.value)
console.log(this.country.current.value)
const data = {
firstName: this.firstName.current.value,
lastName: this.lastName.current.value,
title: this.title.current.value,
country: this.country.current.value,
}
// burası backend api'ye bağlandığımız ve veriyi veritabanına gönderdiğimiz yerdir
console.log(data)
}
render() {
return (
<div className='App'>
<h3>Öğrenci Ekle</h3>
<form onSubmit={this.handleSubmit}>
<div>
<input
type='text'
name='firstName'
placeholder='Ad'
ref={this.firstName}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='lastName'
placeholder='Soyad'
ref={this.lastName}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='country'
placeholder='Ülke'
ref={this.country}
onChange={this.handleChange}
/>
</div>
<div>
<input
type='text'
name='title'
placeholder='Ünvan'
ref={this.title}
onChange={this.handleChange}
/>
</div>
<button className='btn btn-success'>Gönder</button>
</form>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Çoğu zaman kontrolsüz input yerine kontrollü input kullanılır. DOM üzerindeki bir öğeyi hedeflemek istediğinizde, o öğenin içeriğini almak için ref kullanırsınız. Saf JavaScript kullanarak DOM'a doğrudan dokunmayın. Bir React uygulaması geliştirirken DOM'u doğrudan değiştirmeyin; çünkü React'in DOM manipülasyonunu yönetmek için kendi yolu vardır.
# Egzersizler
## Egzersizler: Seviye 1
1. Kontrollü (controlled) input nedir?
2. Kontrolsüz (uncontrolled) input nedir?
3. React'te belirli bir HTML öğesinin içeriğini nasıl alırsınız?
4. React'te DOM'a doğrudan dokunmak neden iyi bir fikir değildir?
5. React'te en sık ne kullanılır? Kontrollü mu yoksa kontrolsüz input mu?
6. Kontrolsüz input yazmak için neye ihtiyaç duyarsınız?
7. Kontrolsüz input yazmak için state gerekli midir?
8. Kontrolsüz input'u ne zaman kullanırsınız?
9. Kontrollü input'u ne zaman kullanırsınız?
10. Form input alanlarını doğrulamak için kontrollü mu yoksa kontrolsüz input mu kullanırsınız?
🎉 TEBRİKLER! 🎉
[<< Gün 12](../12_Gun_Formlar/12_formlar.md) | [Gün 14 >>](../14_Gun_Bilesen_Yasam_Donguleri/14_bilesen_yasam_donguleri.md)

@ -0,0 +1,619 @@
<div align="center">
<h1> 30 Days Of React: Bileşen Yaşam Döngüleri (Component Life Cycles)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 13](../13_Gun_Kontrollü_ve_Kontrolsüz_Input/13_kontrolsuz_input.md) | [Gün 15 >>](../15_Gun_Üçüncü_Taraf_Paketler/15_ucuncu_taraf_paketler.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_14.jpg)
- [Bileşen Yaşam Döngüleri (Component Life Cycles)](#bileşen-yaşam-döngüleri-component-life-cycles)
- [Bileşen Yaşam Döngüsü Nedir?](#bileşen-yaşam-döngüsü-nedir)
- [Montaj (Mounting)](#montaj-mounting)
- [Constructor](#constructor)
- [getDerivedStateFromProps](#getderivedstatefromprops)
- [Render](#render)
- [ComponentDidMount](#componentdidmount)
- [Güncelleme (Updating)](#güncelleme-updating)
- [getDerivedStateFromProps](#getderivedstatefromprops-1)
- [shouldComponentUpdate](#shouldcomponentupdate)
- [render](#render-1)
- [componentDidUpdate](#componentdidupdate)
- [Kaldırma (Unmounting)](#kaldırma-unmounting)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Bileşen Yaşam Döngüleri (Component Life Cycles)
## Bileşen Yaşam Döngüsü Nedir?
Bileşen yaşam döngüsü, bir React uygulamasında bir bileşenin DOM'a eklenmesi (mounting), güncellenmesi (updating) ve yok edilmesi (destroying) sürecidir. Bileşen yaşam döngüsünü insanın büyüme süreciyle ilişkilendirebilirsiniz: doğum, yetişkinlik, yaşlılık ve ölüm.
React'te bir bileşen de DOM'a ilk kez eklenebilir (render edilebilir), veriler değiştirilerek güncellenebilir ve artık gerekmediğinde yok edilebilir. React'te her bileşenin üç ana aşaması vardır:
- Montaj (Mounting)
- Güncelleme (Updating)
- Kaldırma (Unmounting)
## Montaj (Mounting)
React bileşenini DOM'a render etmek veya yerleştirmek, montaj (mounting) olarak adlandırılır. Aşağıdaki yerleşik metodlar, bir React bileşeninin montajı sırasında verilen sırayla çalışır:
1. constructor()
2. static getDerivedStateFromProps()
3. render()
4. componentDidMount()
Class tabanlı bir bileşen oluştururken yerleşik render metodunu kullandık ve bu metod tüm class tabanlı bileşenlerde zorunludur; diğer metodlar ise isteğe bağlıdır. Aşağıdaki kod parçasını çalıştırarak farklı metodların çalışma sırasını görün.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: '',
}
}
static getDerivedStateFromProps(props, state) {
console.log(
'Ben getDerivedStateFromProps\'um ve ikinci çalışacak olan benim.'
)
return null
}
componentDidMount() {
console.log('Ben componentDidMount\'um ve en son çalışacak olan benim.')
}
render() {
console.log('Ben render\'ım ve üçüncü çalışacak olan benim.')
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### Constructor
Günümüzde class tabanlı bileşenleri constructor olmadan yazıyoruz ve state'i de constructor'ın dışında tanımlayabiliyoruz. React'in eski sürümlerinde state her zaman constructor'ın içinde olurdu.
constructor() metodu bileşen başlatıldığında diğer tüm metodlardan önce çalışır ve başlangıç state'i ile diğer değerlerin tanımlandığı yerdir.
Class'ta üst sınıftan miras almak için constructor parametresi kullanılır; React'te ise constructor bir props parametresi alır ve super metodu da çağrılmak zorundadır.
Constructor ve state hakkındaki kod parçasına bakın.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: '',
}
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h2>Constructor İlk Çalışandır</h2>
<p>Yazar: {this.state.firstName}</p>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### getDerivedStateFromProps
Adından anlaşılacağı üzere bu metod, props'tan bir state türetir. getDerivedStateFromProps() metodu, bileşen DOM'da render edilmeden hemen önce çağrılır. Bu, başlangıç props'larına göre state nesnesini ayarlamak için doğru yerdir.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const User = ({ firstName }) => (
<div>
<h1>{firstName}</h1>
</div>
)
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
// state constructor'ın içinde veya dışında yazılabilir
// dışında yazılırsa this anahtar kelimesine gerek yoktur
this.state = {
firstName: 'Ahmet',
}
}
static getDerivedStateFromProps(props, state) {
console.log(
'Ben getDerivedStateFromProps\'um ve ikinci çalışacak olan benim.'
)
return { firstName: props.firstName }
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h3>getDerivedStateFromProps</h3>
<User firstName={this.state.firstName} />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App firstName='Asabeneh' />, rootElement)
```
### Render
render metodu, class tabanlı bir bileşen oluşturduğumuzda zorunlu bir metoddur. render metodu, JSX'i döndürdüğümüz yerdir. render metodu, state'te her değişiklik olduğunda yeniden çalışır. State'inizi render metodunun içinde belirlemeyin.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const User = ({ firstName }) => (
<div>
<h1>{firstName}</h1>
</div>
)
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
// state constructor'ın içinde veya dışında yazılabilir
// dışında yazılırsa this anahtar kelimesine gerek yoktur
this.state = {
firstName: 'Ahmet',
}
}
render() {
// Bunu asla yapmayın
// render metodunun içinde state'i sıfırlamayın, bunun için ayrı bir metod oluşturun
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h3>Render metodu</h3>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App firstName='Asabeneh' />, rootElement)
```
### ComponentDidMount
Metodun adından da anlaşılacağı üzere bu metod, bileşen render edildikten sonra çağrılır. Zaman aralığı belirlemek ve API çağrısı yapmak için doğru yerdir. Aşağıda componentDidMount metodunda setTimeout kullanımını inceleyin.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
}
}
componentDidMount() {
console.log('Ben componentDidMount\'um ve en son çalışacak olan benim.')
// 3 saniye sonra state'i sıfırlar
setTimeout(() => {
this.setState({
firstName: 'Asabeneh',
})
}, 3000)
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h2>componentDidMount Metodu</h2>
{this.state.firstName}
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Yukarıdaki kod parçasında, componentDidMount metodunun içinde setTimeout'un nasıl kullanılacağını gördük. Bir sonraki örnekte fetch kullanarak bir API çağrısı uygulayacağız.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
data: [],
}
}
componentDidMount() {
console.log('Ben componentDidMount\'um ve en son çalışacak olan benim.')
const API_URL = 'https://restcountries.eu/rest/v2/all'
fetch(API_URL)
.then((response) => {
return response.json()
})
.then((data) => {
console.log(data)
this.setState({
data,
})
})
.catch((error) => {
console.log(error)
})
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<div>
<div>
{' '}
<img src={country.flag} alt={country.name} />{' '}
</div>
<div>
<h1>{country.name}</h1>
<p>Başkent: {country.capital}</p>
<p>Nüfus: {country.population}</p>
</div>
</div>
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Bazen verileri render etmek için ayrı bir metod kullanmak daha iyi olabilir. Aşağıdaki örneğe bakın:
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
data: [],
}
}
componentDidMount() {
console.log('Ben componentDidMount\'um ve en son çalışacak olan benim.')
const API_URL = 'https://restcountries.eu/rest/v2/all'
fetch(API_URL)
.then((response) => {
return response.json()
})
.then((data) => {
console.log(data)
this.setState({
data,
})
})
.catch((error) => {
console.log(error)
})
}
renderCountries = () => {
return this.state.data.map((country) => {
return (
<div>
<div>
{' '}
<img src={country.flag} alt={country.name} />{' '}
</div>
<div>
<h1>{country.name}</h1>
<p>Nüfus: {country.population}</p>
</div>
</div>
)
})
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>{this.renderCountries()}</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
## Güncelleme (Updating)
Bir bileşen DOM'a eklendikten sonra, state veya props değiştiğinde güncellenebilir. Bir React bileşeninin güncellenmesi, props veya state değişikliklerinden kaynaklanabilir. Bir bileşen yeniden render edilirken aşağıdaki metodlar sırayla çağrılır:
1. static getDerivedStateFromProps()
2. shouldComponentUpdate()
3. render()
4. getSnapshotBeforeUpdate()
5. componentDidUpdate()
### getDerivedStateFromProps
Montaj aşamasına benzer şekilde, getDerivedStateFromProps güncelleme aşamasında da çağrılabilir. getDerivedStateFromProps, bir bileşen güncellendiğinde çağrılan ilk metoddur.
### shouldComponentUpdate
shouldComponentUpdate() yerleşik yaşam döngüsü metodu bir boolean (true/false) döndürmelidir. Bu metod true döndürmezse uygulama güncellenmez.
Metod true döndürmezse uygulama hiçbir zaman güncellenmez. Bu, örneğin belirli bir noktaya ulaşıldığında (oyun, abonelik) kullanıcıyı bloke etmek veya belirli bir kullanıcıyı engellemek için kullanılabilir.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
data: [],
}
}
shouldComponentUpdate(nexProps, nextState) {
console.log(nextProps, nextState)
// true döndürülürse uygulama asla güncellenmez
return true
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Örneğin, 30 gün sonra meydan okumayı durdurmak istersek, günü 1'den 30'a kadar artırabilir ve 30. günde uygulamayı engelleyebiliriz.
Örneğe bakın.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
day: 1,
}
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps, nextState)
console.log(nextState.day)
if (nextState.day > 31) {
return false
} else {
return true
}
}
// doChallenge günü bir artırır
doChallenge = () => {
this.setState({
day: this.state.day + 1,
})
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<button onClick={this.doChallenge}>Meydan Okuma Yap</button>
<p>Meydan Okuma: Gün {this.state.day}</p>
{this.state.congratulate && <h2>{this.state.congratulate}</h2>}
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### render
Bileşenin montaj aşamasında belirttiğimiz gibi, render() metodu bir bileşen güncellendiğinde de çağrılır. Yeni değişikliklerle birlikte HTML'yi DOM'a yeniden render etmek zorundadır.
### componentDidUpdate
componentDidUpdate metodu iki parametre alır: prevProps ve prevState. Bileşen DOM'da güncellendikten sonra çağrılır.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
firstName: 'Ahmet',
data: [],
}
}
componentDidUpdate(prevProps, prevState) {
console.log(prevState, prevProps)
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Yukarıdaki iki yaşam döngüsü metodunu birlikte kullanalım.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor(props) {
super(props)
console.log('Ben constructor\'um ve ilk çalışacak olan benim.')
this.state = {
day: 1,
congratulate: '',
}
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps, nextState)
console.log(nextState.day)
if (nextState.day > 31) {
return false
} else {
return true
}
}
doChallenge = () => {
this.setState({
day: this.state.day + 1,
})
}
componentDidUpdate(prevProps, prevState) {
if (prevState.day == 30) {
this.setState({
congratulate: 'Tebrikler, meydan okuma tamamlandı!',
})
}
console.log(prevState, prevProps)
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<button onClick={this.doChallenge}>Meydan Okuma Yap</button>
<p>Meydan Okuma: Gün {this.state.day}</p>
{this.state.congratulate && <h2>{this.state.congratulate}</h2>}
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
## Kaldırma (Unmounting)
Bir bileşenin yaşam döngüsündeki son aşama kaldırma (unmounting) aşamasıdır. Kaldırma aşaması, bileşeni DOM'dan siler.
componentWillUnmount metodu, bir bileşen kaldırıldığında çağrılan tek yerleşik metoddur.
# Egzersizler
## Egzersizler: Seviye 1
1. Bileşen yaşam döngüsü nedir?
2. Yaşam döngülerinin amacı nedir?
3. Bir bileşen yaşam döngüsünün üç aşaması nelerdir?
4. Montaj (mounting) ne anlama gelir?
5. Güncelleme (updating) ne anlama gelir?
6. Kaldırma (unmounting) ne anlama gelir?
7. En yaygın kullanılan yerleşik montaj yaşam döngüsü metodu hangisidir?
8. Montaj yaşam döngüsü metodları nelerdir?
9. Güncelleme yaşam döngüsü metodları nelerdir?
10. Kaldırma yaşam döngüsü metodu nedir?
## Egzersizler: Seviye 2
Yakında
## Egzersizler: Seviye 3
Yakında
🎉 TEBRİKLER! 🎉
[<< Gün 13](../13_Gun_Kontrollü_ve_Kontrolsüz_Input/13_kontrolsuz_input.md) | [Gün 15 >>](../15_Gun_Üçüncü_Taraf_Paketler/15_ucuncu_taraf_paketler.md)

@ -0,0 +1,450 @@
<div align="center">
<h1> 30 Days Of React: Üçüncü Taraf Paketler (Third Party Packages)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 14](../14_Gun_Bilesen_Yasam_Donguleri/14_bilesen_yasam_donguleri.md) | [Gün 16 >>](../16_Gun_Yuksek_Duzey_Bilesen/16_yuksek_duzey_bilesen.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_15.jpg)
- [Üçüncü Taraf Paketler (Third Party Packages)](#üçüncü-taraf-paketler-third-party-packages)
- [NPM veya Yarn](#npm-veya-yarn)
- [node-sass](#node-sass)
- [CSS modules](#css-modules)
- [axios](#axios)
- [react-icons](#react-icons)
- [moment](#moment)
- [styled-components](#styled-components)
- [reactstrap](#reactstrap)
- [lodash](#lodash)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Üçüncü Taraf Paketler (Third Party Packages)
npm kayıt defterinde 1,4 milyondan fazla JavaScript paketi bulunmaktadır. Artık neredeyse her türlü sorun için bir paket mevcuttur. Tekerleği yeniden icat etmek yerine tekerleği nasıl kullanacağımızı bilmemiz gerekir. Bu bölümde npm paketlerini nasıl kullanacağımızı öğreneceğiz ve React uygulamaları için en yaygın paketleri uygulayacağız. 10 Ekim 2020 itibarıyla npm kayıt defterinin popüler paketleri, toplam paket sayısı, haftalık indirmeler ve aylık indirmeler aşağıda gösterildiği gibidir.
![NPM paketleri](../../images/npm_package_day_15.png)
React uygulamalarınızda aşağıdaki paketlere bir şekilde ihtiyaç duyabilirsiniz. Özellikle node-sass, moment ve axios bazı projeler için önemlidir.
- [node-sass](https://www.npmjs.com/package/node-sass)
- [moment](https://www.npmjs.com/package/moment)
- [axios](https://www.npmjs.com/package/axios)
- [react-icons](https://react-icons.github.io/react-icons/)
- [styled-components](https://styled-components.com/)
- [reactstrap](https://reactstrap.github.io/)
- [lodash](https://www.npmjs.com/package/lodash)
- [uuid](https://www.npmjs.com/package/uuid)
## NPM veya Yarn
Paket yüklemek için npm ya da yarn kullanabilirsiniz. [yarn](https://yarnpkg.com) kullanmak istiyorsanız ayrıca kurmanız gerekir. Paket yönetim araçlarından birini tercih etmenizi öneririm. Aynı uygulamada her iki paket yönetim aracını aynı anda kullanmayın.
Bir uygulamaya paketlerin nasıl yükleneceğini görelim. Önce proje dizinine gidip aşağıdaki komutu yazıyoruz.
```sh
// sözdizimi, i veya install kullanabiliriz
npm i paket-adı
// veya
yarn add paket-adı
```
### node-sass
Sass, CSS fonksiyonu, iç içe yazım (nesting) ve çok daha fazlasını yazmayı sağlayan bir CSS ön işlemcisidir. Sass'ın gücünden faydalanmak için node-sass'ı yükleyelim.
npm kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ npm install node-sass
```
yarn kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ yarn add node-sass
```
node-sass yüklendikten sonra React'te Sass kullanmaya başlayabilirsiniz. Bir styles klasörü oluşturun ve bu klasörün içine test.scss dosyası ekleyin. Bu dosyayı üzerinde çalıştığınız component'e veya index.js'ye import edin. node-sass'ı component'e import etmenize gerek yoktur.
```css
/* ./styles/header.scss */
header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
}
```
```js
// Header.js
import React from 'react'
import './styles/header.scss
const Header = () = (
<header>
<div className='header-wrapper'>
<h1>30 Günde React</h1>
<h2>React'e Başlangıç</h2>
<h3>JavaScript Kütüphanesi</h3>
<p>Eğitmen: Asabeneh Yetayeh</p>
<small>15 Ekim, 2020</small>
</div>
</header>
)
export default Header
```
```js
// App.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './styles/header.scss
class App extends Component {
render() {
return (
<div className='App'>
<Header />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### CSS modules
Sass'a ek olarak, React'te CSS modüllerinin nasıl kullanılacağını bilmek de faydalıdır. React uygulamalarında CSS modülü kullanmak için ayrı bir paket yüklememize gerek yoktur. CSS modülü, saf CSS veya Sass ile birlikte kullanılabilir. CSS modülü için isimlendirme kuralı, belirli bir ismin ardından nokta ve module ifadesi gelir (test.module.css veya test.module.scss).
İsimlendirme:
```js
// Sass için isimlendirme
// CSS için isimlendirme
;[isim].module.scss[isim].module.css
```
```css
/* ./styles/header.module.scss */
.header {
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
}
.header-wrapper {
font-weight:500
border: 5px solid orange;
}
```
```js
// Header.js
import React from 'react'
import headerStyles from './styles/header.module.scss
// Sınıf adını destructure edebiliriz
const {header, headerWrapper} = headerStyles
const Header = () = (
<header className = {headerStyles.header}>
<div className={headerStyles.headerWrapper}>
<h1>30 Günde React</h1>
<h2>React'e Başlangıç</h2>
<h3>JavaScript Kütüphanesi</h3>
<p>Eğitmen: Asabeneh Yetayeh</p>
<small>15 Ekim, 2020</small>
</div>
</header>
)
export default Header
```
```js
// App.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './styles/header.scss
class App extends Component {
render() {
return (
<div className='App'>
<Header />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### axios
Axios, veri almak için HTTP istekleri yapabilen bir JavaScript kütüphanesidir. Bu bölümde GET isteğini ele alacağız. Ancak [axios](https://github.com/axios/axios) ile tüm istek türlerini yapmak mümkündür (GET, POST, PUT, PATCH, DELETE).
npm kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ npm install axios
```
yarn kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ yarn add axios
```
```js
import React, { Component } from 'react'
// axios, sunucuya veri almak için istek gönderen bir pakettir
import axios from 'axios'
import ReactDOM from 'react-dom'
class App extends Component {
state = {
data: [],
}
componentDidMount() {
const API_URL = 'https://restcountries.eu/rest/v2/all'
axios
.get(API_URL)
.then((response) => {
this.setState({
data: response.data,
})
})
.catch((error) => {
console.log(error)
})
}
renderCountries = () => {
return this.state.data.map((country) => {
const languageOrLanguages =
country.languages.length > 1 ? 'Diller' : 'Dil'
const formatLanguages = country.languages
.map(({ name }) => name)
.join(', ')
return (
<div>
<div>
{' '}
<img src={country.flag} alt={country.name} />{' '}
</div>
<div>
<h1>{country.name}</h1>
<p>Başkent: {country.capital}</p>
<p>
{languageOrLanguages}: {formatLanguages}
</p>
<p>Nüfus: {country.population}</p>
</div>
</div>
)
})
}
render() {
return (
<div className='App'>
<h1>Axios ile Veri Çekme</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>{this.renderCountries()}</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Axios'u await ve async fonksiyonlarla birlikte kullanabiliriz. await ve async kullanmak için componentDidMount'un dışında ayrı bir fonksiyon oluşturmamız gerekir. Await ve async uygularsak hatalar try ve catch ile ele alınmalıdır.
### react-icons
İkonlar bir web sitesinin ayrılmaz bir parçasıdır. Farklı SVG ikonları kullanmak için:
npm kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ npm install react-icons
```
yarn kullanarak:
```sh
Asabeneh@DESKTOP-KGC1AKC MINGW64 ~/Desktop/30-days-of-react$ yarn add react-icons
```
```js
import React, { Component } from 'react'
import axios from 'axios'
import ReactDOM from 'react-dom'
import moment from 'moment'
import {
TiSocialLinkedinCircular,
TiSocialGithubCircular,
TiSocialTwitterCircular,
} from 'react-icons/ti'
const Footer = () => (
<footer>
<h3>30 Günde React</h3>
<div>
<TiSocialLinkedinCircular />
<TiSocialGithubCircular />
<TiSocialTwitterCircular />
</div>
<div>
<small> Telif Hakkı &copy; {new Date().getFullYear()} </small>
</div>
</footer>
)
class App extends Component {
render() {
return (
<div className='App'>
<h1>İkon Dünyasına Hoş Geldiniz</h1>
<Footer />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### moment
Moment, farklı zaman formatları sunan küçük bir JavaScript kütüphanesidir.
```sh
npm install moment
```
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
render() {
return (
<div className='App'>
<h1>moment Nasıl Kullanılır?</h1>
<p>Bu meydan okuma {moment('2020-10-01').fromNow()} başladı</p>
<p>Meydan okuma {moment('2020-10-30').fromNow()} sona erecek</p>
<p>Bugün {moment(new Date()).format('MMMM DD, YYYY HH:mm')}</p>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### styled-components
Bir bileşeni şekillendirmek için etiketli şablon değişmezlerini (tagged template literals) kullanır. Bileşenler ve stiller arasındaki eşleşmeyi kaldırır. Bu, stillerinizi tanımlarken aslında stillerinizin eklendiği normal bir React bileşeni oluşturduğunuz anlamına gelir.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import styled from 'styled-components'
const Title = styled.h1`
font-size: 70px;
font-weight: 300;
`
const Header = styled.header`
background-color: #61dbfb;
padding: 25;
padding: 10px;
margin: 0;
`
class App extends Component {
render() {
return (
<div className='App'>
<Header>
<div>
<Title>30 Günde React</Title>
<h2>React'e Başlangıç</h2>
<h3>JavaScript Kütüphanesi</h3>
<p>Eğitmen: Asabeneh Yetayeh</p>
<small>15 Ekim, 2020</small>
</div>
</Header>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
### reactstrap
[reactstrap](https://reactstrap.github.io/) paketi, bileşenleri Bootstrap ile birlikte kullanmayı sağlar.
### lodash
Resmi lodash belgelerine göre: 'Modülerlik, performans ve ekstralar sunan modern bir JavaScript yardımcı programı kütüphanesi.'
_classnames_ ve _validator_ paketlerini de nasıl kullanacağınızı öğrenmeye çalışın.
# Egzersizler
## Egzersizler: Seviye 1
1. Paket nedir?
2. Üçüncü taraf (third party) paket nedir?
3. Üçüncü taraf paket kullanmak zorunda mısınız?
4. Bir üçüncü taraf paketin popülerliğini ve kararlılığını nasıl anlarsınız?
5. npm kayıt defterinde kaç JavaScript paketi bulunmaktadır?
6. Üçüncü taraf paket nasıl yüklenir?
7. En sık hangi paketleri kullanırsınız?
8. Veri çekmek için hangi paketi kullanırsınız?
9. classnames paketinin amacı nedir?
10. validator paketinin amacı nedir?
## Egzersizler: Seviye 2
1. Sass'ı nasıl kullanacağınızı öğrenin.
2. axios'u nasıl kullanacağınızı öğrenin.
3. moment ve react-icons'ı nasıl kullanacağınızı öğrenin.
4. 12. gündeki formu doğrulamak için validator paketini kullanın.
5. Bir mantığa dayalı olarak sınıfı değiştirmek için classnames'i kullanın.
## Egzersizler: Seviye 3
🎉 TEBRİKLER! 🎉
[<< Gün 14](../14_Gun_Bilesen_Yasam_Donguleri/14_bilesen_yasam_donguleri.md) | [Gün 16 >>](../16_Gun_Yuksek_Duzey_Bilesen/16_yuksek_duzey_bilesen.md)

@ -0,0 +1,212 @@
<div align="center">
<h1> 30 Days Of React: Yüksek Düzey Bileşen (Higher Order Component)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 15](../15_Gun_Üçüncü_Taraf_Paketler/15_ucuncu_taraf_paketler.md) | [Gün 17 >>](../17_Gun_React_Router/17_react_router.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_16.jpg)
- [Yüksek Düzey Bileşen (Higher Order Component)](#yüksek-düzey-bileşen-higher-order-component)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Yüksek Düzey Bileşen (Higher Order Component)
Yüksek düzey bileşen (Higher Order Component) terimi, JavaScript'teki yüksek düzey fonksiyon (higher order function) kavramına benzerdir. JavaScript'te yüksek düzey fonksiyon; başka bir fonksiyonu parametre olarak alan veya başka bir fonksiyon döndüren fonksiyondur.
Yüksek düzey fonksiyona benzer şekilde, yüksek düzey bileşen bir bileşen alır ve başka bir bileşen döndürür.
Bu tanım örneklerle daha anlamlı hale gelecektir. Daha iyi anlamak için aşağıdaki örneğe bakın.
```js
// Yüksek Düzey Bileşen (HOC) yazmanın bir yolu
import React from 'react'
const higherOrderComponent = (Component) => {
return (props) => {
return <Component {...props} />
}
}
```
Çoğu zaman üçüncü taraf kütüphaneler yüksek düzey bileşen kullanır. Örneğin redux, react-router-dom ve material-ui yüksek düzey bileşen kullanır.
```js
import React from 'react'
const Button = ({ onClick, text, style }) => {
return (
<button onClick={onClick} style={style}>
{text}
</button>
)
}
const buttonWithStyle = (CompParam) => {
const buttonStyles = {
backgroundColor: '#61dbfb',
padding: '10px 25px',
border: 'none',
borderRadius: 5,
margin: 3,
cursor: 'pointer',
fontSize: 18,
color: 'white',
}
return (props) => {
return <CompParam {...props} style={buttonStyles} />
}
}
const NewButton = buttonWithSuperPower(Button)
class App extends Component {
render() {
return (
<div className='App'>
<Button text='Stilsiz' />
<NewButton text='Stillendirilmiş Buton' />
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
buttonWithStyle yüksek düzey bileşenini bileşene ek olarak daha fazla parametre alacak şekilde geliştirelim.
```js
import React from 'react'
const Button = ({ onClick, text, style }) => {
return (
<button onClick={onClick} style={style}>
{text}
</button>
)
}
const buttonWithStyles = (CompParam, name = 'default') => {
const colors = [
{
name: 'default',
backgroundColor: '#e7e7e7',
color: '#000000',
},
{
name: 'react',
backgroundColor: '#61dbfb',
color: '#ffffff',
},
{
name: 'success',
backgroundColor: '#4CAF50',
color: '#ffffff',
},
{
name: 'info',
backgroundColor: '#2196F3',
color: '#ffffff',
},
{
name: 'warning',
backgroundColor: '#ff9800',
color: '#ffffff',
},
{
name: 'danger',
backgroundColor: '#f44336',
color: '#ffffff',
},
]
const { backgroundColor, color } = colors.find((c) => c.name === name)
const buttonStyles = {
backgroundColor,
padding: '10px 45px',
border: 'none',
borderRadius: 3,
margin: 3,
cursor: 'pointer',
fontSize: '1.25rem',
color,
}
return (props) => {
return <CompParam {...props} style={buttonStyles} />
}
}
const NewButton = buttonWithSuperPower(Button)
const ReactButton = buttonWithSuperPower(Button, 'react')
const InfoButton = buttonWithSuperPower(Button, 'info')
const SuccessButton = buttonWithSuperPower(Button, 'success')
const WarningButton = buttonWithSuperPower(Button, 'warning')
const DangerButton = buttonWithSuperPower(Button, 'danger')
class App extends Component {
render() {
return (
<div className='App'>
<Button text='Stil Yok' onClick={() => alert('Henüz stillendirilmedim')} />
<NewButton
text='Stillendirilmiş Buton'
onClick={() => alert('Ben varsayılan stilim')}
/>
<ReactButton text='React' onClick={() => alert('React rengine sahibim')} />
<InfoButton
text='Bilgi'
onClick={() => alert('Bilgi rengiyle stillendirildim')}
/>
<SuccessButton text='Başarılı' onClick={() => alert('Ben başarılıyım')} />
<WarningButton
text='Uyarı'
onClick={() => alert('Sizi birçok kez uyarıyorum')}
/>
<DangerButton
text='Tehlike'
onClick={() => alert('Ah hayır, geri yükleyemezsiniz')}
/>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Yukarıdaki örnek, Yüksek Düzey Bileşenin bir kullanım durumudur. Ancak kullanım alanı yalnızca basit bir butonu şekillendirmekle sınırlı değildir. Çok daha fazla kullanım alanı vardır; bileşeni yeniden kullanmamıza ve bir bileşeni stil ve işlevsellikle geliştirmemize olanak tanır. İlerleyen bölümlerde React Router'ı ele alacağız ve HOC kullanacağız; bir bileşenin başka bir bileşeni sardığını gördüğünüzde şaşırmayacaksınız.
# Egzersizler
## Egzersizler: Seviye 1
1. Yüksek düzey fonksiyon nedir?
2. Yüksek Düzey Bileşen nedir?
3. Yüksek düzey fonksiyon ile yüksek düzey bileşen arasındaki fark nedir?
4. Yüksek düzey bileşen bir bileşeni geliştirmemizi sağlar. (Doğru mu Yanlış mı?)
## Egzersizler: Seviye 2
1. Tüm input türlerini yönetebilen bir yüksek düzey bileşen oluşturun.
## Egzersizler: Seviye 3
Yakında
🎉 TEBRİKLER! 🎉
[<< Gün 15](../15_Gun_Üçüncü_Taraf_Paketler/15_ucuncu_taraf_paketler.md) | [Gün 17 >>](../17_Gun_React_Router/17_react_router.md)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,440 @@
<div align="center">
<h1> 30 Days Of React: Fetch ve Axios (Fetch and Axios)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 17](../17_Gun_React_Router/17_react_router.md) | [Gün 19 >>](../19_Gun_Projeler/19_projeler.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_18.jpg)
- [Fetch ve Axios (Fetch and Axios)](#fetch-ve-axios-fetch-and-axios)
- [Fetch](#fetch)
- [Axios](#axios)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
- [Egzersizler: Seviye 2](#egzersizler-seviye-2)
- [Egzersizler: Seviye 3](#egzersizler-seviye-3)
# Fetch ve Axios (Fetch and Axios)
## Fetch
Günümüzde JavaScript, HTTP istekleri yapmak için fetch API'sini sunmaktadır. Fetch tüm tarayıcılar tarafından desteklenmeyebilir; bu nedenle tarayıcı desteği için ek paket yüklememiz gerekebilir. Ancak axios kullanırsak tarayıcı desteği için ek pakete ihtiyaç duymayız. Axios kodu fetch'e göre daha temiz görünmektedir. Bu bölümde fetch ile axios arasındaki farka bakacağız. Fetch'in tarayıcı desteğini öğrenmek istiyorsanız [caniuse](https://caniuse.com/ciu/index) web sitesinden kontrol edebilirsiniz. Bugün itibarıyla %95,62 tarayıcı desteğine sahiptir.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
const formattedCapital =
capital.length > 0 ? (
<>
<span>Başkent: </span>
{capital}
</>
) : (
''
)
const formatLanguage = languages.length > 1 ? `Diller` : `Dil`
console.log(languages)
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div className='country_text'>
<p>{formattedCapital}</p>
<p>
<span>{formatLanguage}: </span>
{languages.map((language) => language.name).join(', ')}
</p>
<p>
<span>Nüfus: </span>
{population.toLocaleString()}
</p>
<p>
<span>Para Birimi: </span>
{currency}
</p>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
}
componentDidMount() {
const url = 'https://restcountries.eu/rest/v2/all'
fetch(url)
.then((response) => {
return response.json()
})
.then((data) => {
console.log(data)
this.setState({
data,
})
})
.catch((error) => {
console.log(error)
})
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Yukarıdaki kodu kısaltmak ve temizlemek için async ve await kullanabiliriz.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
const formattedCapital =
capital.length > 0 ? (
<>
<span>Başkent: </span>
{capital}
</>
) : (
''
)
const formatLanguage = languages.length > 1 ? `Diller` : `Dil`
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div className='country_text'>
<p>{formattedCapital}</p>
<p>
<span>{formatLanguage}: </span>
{languages.map((language) => language.name).join(', ')}
</p>
<p>
<span>Nüfus: </span>
{population.toLocaleString()}
</p>
<p>
<span>Para Birimi: </span>
{currency}
</p>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
}
componentDidMount() {
this.fetchCountryData()
}
fetchCountryData = async () => {
const url = 'https://restcountries.eu/rest/v2/all'
const response = await fetch(url)
const data = await response.json()
this.setState({
data,
})
}
render() {
return (
<div className='App'>
<h1>Fetch ile API Çekme</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Async ve await kullandığımızda hatayı try ve catch ile ele alırız. Yukarıdaki koda try catch bloğu ekleyelim.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
const Country = ({ country: { name, flag, population } }) => {
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div className='country_text'>
<p>
<span>Nüfus: </span>
{population}
</p>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
}
componentDidMount() {
this.fetchCountryData()
}
fetchCountryData = async () => {
const url = 'https://restcountries.eu/rest/v2/all'
try {
const response = await fetch(url)
const data = await response.json()
this.setState({
data,
})
} catch (error) {
console.log(error)
}
}
render() {
return (
<div className='App'>
<h1>Fetch ile API Çekme</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Şimdi aynı API çağrısını axios ile nasıl yapacağımıza bakalım.
Birden fazla API çağrımız varsa fetch ile nasıl yapabiliriz?
## Axios
Axios üçüncü taraf bir pakettir ve npm ile yüklememiz gerekir. HTTP istekleri yapmak için en popüler yoldur (GET, POST, PUT, PATCH, DELETE). Bu örnekte yalnızca GET isteğini ele alacağız.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
const Country = ({
country: { name, capital, flag, languages, population, currency },
}) => {
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div className='country_text'>
<p>
<span>Nüfus: </span>
{population}
</p>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
}
componentDidMount() {
const url = 'https://restcountries.eu/rest/v2/all'
axios
.get(url)
.then((response) => {
this.setState({
data: response.data,
})
})
.catch((error) => {
console.log(error)
})
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Axios ile veri çekmeyi async ve await kullanarak da uygulayalım.
```js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'
const Country = ({ country: { name, flag, population } }) => {
return (
<div className='country'>
<div className='country_flag'>
<img src={flag} alt={name} />
</div>
<h3 className='country_name'>{name.toUpperCase()}</h3>
<div className='country_text'>
<p>
<span>Nüfus: </span>
{population}
</p>
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
}
componentDidMount() {
this.fetchCountryData()
}
fetchCountryData = async () => {
const url = 'https://restcountries.eu/rest/v2/all'
try {
const response = await axios.get(url)
const data = await response.data
this.setState({
data,
})
} catch (error) {
console.log(error)
}
}
render() {
return (
<div className='App'>
<h1>React Bileşen Yaşam Döngüsü</h1>
<h1>API Çağrısı</h1>
<div>
<p>API'de {this.state.data.length} ülke var</p>
<div className='countries-wrapper'>
{this.state.data.map((country) => (
<Country country={country} />
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)
```
Gördüğünüz gibi fetch ile axios arasında çok fazla fark yoktur. Ancak tarayıcı desteği ve kullanım kolaylığıısından fetch'e kıyasla axios kullanmanızı öneririm.
# Egzersizler
## Egzersizler: Seviye 1
1. HTTP isteği nedir?
2. En yaygın HTTP istekleri nelerdir?
3. Fetch nedir?
4. Axios nedir?
5. Fetch ile axios arasındaki fark nedir?
6. HTTP istekleri yapmak için fetch mi yoksa axios mu tercih edersiniz?
## Egzersizler: Seviye 2
1. Aşağıdaki [API](https://api.thecatapi.com/v1/breeds)'de kedilerin ortalama metrik ağırlığını ve yaşam süresini bulun. API'de 67 kedi ırkı bulunmaktadır.
![Ortalama kedi ağırlığı ve yaşı](../../images/average_cat_weight_and_age.png)
## Egzersizler: Seviye 3
1. Kaç ülkede kedi ırkı bulunmaktadır?
2. Hangi ülkede en fazla kedi ırkı var?
3. Ülkeleri sahip oldukları kedi ırkı sayısına göre artan sırayla sıralayın.
🎉 TEBRİKLER! 🎉
[<< Gün 17](../17_Gun_React_Router/17_react_router.md) | [Gün 19 >>](../19_Gun_Projeler/19_projeler.md)

@ -0,0 +1,38 @@
<div align="center">
<h1> 30 Days Of React: Projeler (Projects)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 18](../18_Gun_Fetch_ve_Axios/18_fetch_ve_axios.md) | [Gün 20 >>](../20_Gun_Projeler/20_projeler.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_19.jpg)
- [Projeler](#projeler)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
# Projeler
Bu noktaya kadar geldiğiniz için tebrikler. Artık React hakkında sağlam bir anlayışa sahipsiniz. React'in en önemli özelliklerinin büyük bölümünü ele aldığımıza inanıyorum ve artık projeler üzerinde çalışmaya hazırsınız. Şimdiye kadar öğrendiklerimiz React'in eski sürümüne aittir. 20. Günden itibaren React Hooks'u öğreneceğiz. Önümüzdeki üç gün boyunca yalnızca projeler üzerinde çalışacaksınız.
# Egzersizler
## Egzersizler: Seviye 1
Aşağıdaki iki API'yi kullanın: [tüm kediler](https://api.thecatapi.com/v1/breeds) ve [tek kedi](https://api.thecatapi.com/v1/images/search?breed_id=abys). Tek kedi API'sinde kedinin görselini içeren url özelliğini alabilirsiniz.
Sonucunuz şu şekilde görünmelidir: [demo](https://www.30daysofreact.com/day-19/cats).
🎉 TEBRİKLER! 🎉
[<< Gün 18](../18_Gun_Fetch_ve_Axios/18_fetch_ve_axios.md) | [Gün 20 >>](../20_Gun_Projeler/20_projeler.md)

@ -0,0 +1,38 @@
<div align="center">
<h1> 30 Days Of React: Projeler (Projects)</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar:
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small>
</sub>
</div>
[<< Gün 19](../19_Gun_Projeler/19_projeler.md) | [Gün 21 >>](../../21_Introducing_Hooks/21_introducing_hooks.md)
![30 Days of React banner](../../images/30_days_of_react_banner_day_20.jpg)
- [Projeler](#projeler)
- [Egzersizler](#egzersizler)
- [Egzersizler: Seviye 1](#egzersizler-seviye-1)
# Projeler
Bu noktaya kadar geldiğiniz için tebrikler. Artık React hakkında sağlam bir anlayışa sahipsiniz. React'in en önemli özelliklerinin büyük bölümünü ele aldığımıza inanıyorum ve artık projeler üzerinde çalışmaya hazırsınız. Şimdiye kadar öğrendiklerimiz React'in eski sürümüne aittir. 20. Günden itibaren React Hooks'u öğreneceğiz. Önümüzdeki üç gün boyunca yalnızca projeler üzerinde çalışacaksınız.
# Egzersizler
## Egzersizler: Seviye 1
Aşağıdaki iki API'yi kullanın: [tüm kediler](https://api.thecatapi.com/v1/breeds) ve [tek kedi](https://api.thecatapi.com/v1/images/search?breed_id=abys). Tek kedi API'sinde kedinin görselini içeren url özelliğini alabilirsiniz.
Sonucunuz şu şekilde görünmelidir: [demo](https://www.30daysofreact.com/day-20/cats).
🎉 TEBRİKLER! 🎉
[<< Gün 19](../19_Gun_Projeler/19_projeler.md) | [Gün 21 >>](../../21_Introducing_Hooks/21_introducing_hooks.md)

@ -0,0 +1,45 @@
<div>
<img align="right" width="100%" src="../images/30_days_of_react.jpg" />
</div>
<div align="center">
<h1> 30 Günde React</h1>
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
</a>
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
</a>
<sub>Yazar: <a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
<small> Ekim, 2020</small></sub>
</div>
[Gün 1 >>](./01_Gun_JavaScript_Tazeleyici/01_javascript_tazeleyici.md)
| # Gün | Konular |
| ----- | :---------------------------------------------------------------------------------: |
| 01 | [JavaScript Tazeleyici](./01_Gun_JavaScript_Tazeleyici/01_javascript_tazeleyici.md) |
| 02 | [React'a Giriş](./02_Gun_Reacta_Giris/02_reacta_giris.md) |
| 03 | [Kurulum](./03_Gun_Kurulum/03_kurulum.md) |
| 04 | [Bileşenler](./04_Gun_Bilesenler/04_bilesenler.md) |
| 05 | [Props](./05_Gun_Props/05_props.md) |
| 06 | [Dizi Haritalama](./06_Gun_Dizi_Haritalama/06_dizi_haritalama.md) |
| 07 | [Class Bileşenler](./07_Gun_Class_Bilesenler/07_class_bilesenler.md) |
| 08 | [State (Durum)](./08_Gun_State/08_state.md) |
| 09 | [Koşullu Render](./09_Gun_Kosullu_Render/09_kosullu_render.md) |
| 10 | [Proje Klasör Yapısı](./10_Gun_Proje_Klasor_Yapisi/10_proje_klasor_yapisi.md) |
| 11 | [Olaylar](./11_Gun_Olaylar/11_olaylar.md) |
| 12 | [Formlar](./12_Gun_Formlar/12_formlar.md) |
| 13 | [Kontrollü ve Kontrolsüz Input](./13_Gun_Kontrollü_ve_Kontrolsüz_Input/13_kontrolsuz_input.md) |
| 14 | [Bileşen Yaşam Döngüleri](./14_Gun_Bilesen_Yasam_Donguleri/14_bilesen_yasam_donguleri.md) |
| 15 | [Üçüncü Taraf Paketler](./15_Gun_Üçüncü_Taraf_Paketler/15_ucuncu_taraf_paketler.md) |
| 16 | [Yüksek Düzey Bileşen](./16_Gun_Yuksek_Duzey_Bilesen/16_yuksek_duzey_bilesen.md) |
| 17 | [React Router](./17_Gun_React_Router/17_react_router.md) |
| 18 | [Fetch ve Axios](./18_Gun_Fetch_ve_Axios/18_fetch_ve_axios.md) |
| 19 | [Projeler](./19_Gun_Projeler/19_projeler.md) |
| 20 | [Projeler](./20_Gun_Projeler/20_projeler.md) |
Loading…
Cancel
Save