Önemli: Diğer yazılarımla direkt bağlantılı bir yazıdır. İlk olarak bu yazıdan okumaya başladıysanız, eğitim serisine kısaca bir göz atmanızı tavsiye ederim.
Merhabalar.
Get isteği ile işlemlerimize devam ediyoruz.
Bu yazımda sorguladığımız API endpoint’ine parametre ile veri gönderip data alma işlemini yapacağız.
BlogPost uygulamamıza bu yazımız için bir searchbar yapacağız. Id ile sorgulama yapıp ilgili post’u getirmeye çalışacağız.
İstediğimiz post’u çekebilmek için jsonplaceholder bize aşağıdaki gibi bir endpoint veriyor. Biz de buna istek atacağız.
Burada posts/ kısmından sonra gelen 1 değeri dinamik olacak. O yüzden dinamik olarak buradaki veriyi parametre ile göndermeyi göreceğiz.
https://jsonplaceholder.typicode.com/posts/1
Buraya istek attığımızda elimize gelen data şu şekilde.
Geliştirme Kodlarımız
BlogPost.jsx
import React, { useState } from 'react'
import './BlogPost.css'
import loadingGif from "../../Assets/Images/loading.gif"
const BlogPost = () => {
const [posts, setPosts] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [isData, setIsData] = useState(false);
const [isError, setIsError] = useState(null);
const [showError, setShowError] = useState(false);
const [searchId, setSearchId] = useState('');
const loadPosts = async () => {
try {
setIsLoading(true);
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (response.ok) {
const data = await response.json();
setPosts(data);
setIsLoading(false);
if (data.length === 0 ? setIsData(false) : setIsData(true));
openMessageModal(`${data.length} posts found`);
} else {
setIsLoading(false);
setIsData(false);
openMessageModal('There was an error!');
}
} catch (error) {
setIsData(false);
openMessageModal('There was an error!');
}
};
const openMessageModal = (info) => {
setIsError(info);
setShowError(true);
setTimeout(() => setShowError(false), 5000);
};
const getSearchById = async () => {
try {
if (searchId === '') {
loadPosts();
}
else {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${searchId}`);
if (response.ok) {
const data = await response.json();
setPosts([data]);
setIsLoading(false);
if (data.length === 0 ? setIsData(false) : setIsData(true));
if ([data].length === 0) {
openMessageModal('Data not found');
}
openMessageModal(`${[data].length} posts found`);
}else {
setPosts([]);
openMessageModal('Data not found');
}
}
} catch (error) {
console.error('There was an error!', error);
}
}
const handleSearch = (e) => {
if (e.target.value === '') {
loadPosts();
}
setSearchId(parseInt(e.target.value));
}
return (
<div className="blogPost">
<div className='search'>
<input type="number" name="searchId" value={searchId} onChange={handleSearch} placeholder="Search by ID" />
<button type='button' onClick={getSearchById}>Search</button>
</div>
<button onClick={loadPosts}>Load Posts</button>
{showError && <div className="error">{isError}</div>}
{isLoading &&
<div className="center">
<img src={loadingGif} width={100} alt="Loading" />
</div>
}
{!isData &&
<div className="center">
<h3>There is no data</h3>
</div>
}
{isData &&
posts.map((post) => (
<div key={post.id} className="post">
<h2>{post.title}</h2>
<p>{post.body}</p>
</div>
))}
</div>
);
}
export default BlogPost
BlogPost.css
.blogPost {
display: flex;
flex-direction: column;
align-items: center;
}
.post {
width: 60%;
border: 1px solid #ccc;
border-radius: 5px;
padding: 20px;
margin: 20px 0;
position: relative;
}
button {
padding: 10px 20px;
margin: 20px 0;
border: none;
border-radius: 5px;
background-color: #007BFF;
color: white;
cursor: pointer;
}
.center {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.error {
width: 300px;
height: 50px;
border-radius: 20px;
position: fixed;
top: 20px;
right: 20px;
padding: 10px;
background-color: rgb(255, 0, 0);
color: white;
display: flex;
font-size: 15px;
font-weight: bold;
justify-content: center;
align-items: center;
}
.search {
margin-top: 20px;
display: flex;
direction: column;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 20px;
width: 50%;
}
.search input {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
flex-grow: 1;
margin-right: 10px;
}
.search input, .search button {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.search button {
padding: 10px;
border: none;
background-color: #007BFF;
color: white;
cursor: pointer;
flex-basis: 10%;
}
.search button:hover {
background-color: #0056b3;
}
Görüntümüz aşağıdaki gibi olmalı.
State Ekle
searchId isminde bir state oluşturuyoruz.
const [searchId, setSearchId] = useState('');
SearchBox Kodları
<div className='search'>
<input type="number" name="searchId" value={searchId} onChange={handleSearch} placeholder="Search by ID" />
<button type='button' onClick={getSearchById}>Search</button>
</div>
input üzerinde her girilen yeni değerle onChange event’i tetiklenir. Bu event handleSearch fonksiyonunu tetikler.
Eğer value boş ise tüm postların sorgulaması gerçekleştiriliyor. Eğer bir değer varsa searchId değeri güncellenir.
const handleSearch = (e) => {
if (e.target.value === '') {
loadPosts();
}
setSearchId(parseInt(e.target.value));
}
getSearchById Fonksiyonu
Search Butonuna basılınca getSearchById fonksiyonu tetiklenir.
const getSearchById = async () => {
try {
if (searchId === '') {
loadPosts();
}
else {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${searchId}`);
if (response.ok) {
const data = await response.json();
setPosts([data]);
setIsLoading(false);
if (data.length === 0 ? setIsData(false) : setIsData(true));
if ([data].length === 0) {
openMessageModal('Data not found');
}
openMessageModal(`${[data].length} posts found`);
}else {
setPosts([]);
openMessageModal('Data not found');
}
}
} catch (error) {
console.error('There was an error!', error);
}
}
Parametre endpoint’e aşağıdaki gibi gönderilir.
fetch(`https://jsonplaceholder.typicode.com/posts/${searchId}`);
Gelen data json’a dönüştürülür.
Tekli data çektiğimizde dizi olarak değil tek bir obje olarak geleceği için posts’u güncellerken doğrudan data’yı değil o datayı dizi içine almış halini göndeririz.
Böylece post üzerinde dönen map işlemini yapabilir.
const data = await response.json();
setPosts([data]);
Kodun devamının açıklamasını şöyle yapabiliriz.
isLoading
state’ini false
olarak ayarlıyor.
data
dizisi boşsa, isData
state’ini false
olarak ayarlıyor; değilse true
olarak ayarlıyor.
Eğer veri dizisi boşsa, ‘Veri bulunamadı’ mesajıyla bir modal açıyor.
Kaç gönderi bulunduğunu belirten bir modal açıyor.
Son olarak, searchId
‘yi sıfırlıyor.
} else {
setPosts([]);
openMessageModal('Data Not Found');
}
Eğer API’den gelen yanıt başarısızsa, posts
state’ini boş bir dizi olarak ayarlıyor ve ‘Veri bulunamadı’ mesajıyla bir modal açıyor.
Uygulama Test
Bu yazımızda böyleydi.
Bir sonraki yazımda görüşmek üzere.