Merhabalar.

Get isteği ile işlemlerimize devam ediyoruz.

Load Post butonuna basınca, API’a istek atıyorduk ve blog postlarımız geliyor ve ekranda gösteriyorduk. Bazen API’a attığımız istekler çeşitli sebeplerden hata dönebilir. Ekranda kullanıcıya error ile alakalı bir işlem olduğunu göstermek iyi bir UX geliştirmesidir.

Şimdi uygulamamıza bunu ekleyeceğiz.

Bunu bir isError state’i ile gerçekleştireceğiz.

Error bildirimini bir sağdan açılan modal ile yapmak istiyorum.

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 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);
    }

    return (
        <div className="blogPost">
            <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;
}

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;
}

Adım adım kodlarımıza bakalım.

State’leri Oluştur

error ve modal’ın açılma durumunu kontrol edecek state’lerimizi tanımladık.

const [isError, setIsError] = useState(null);
const [showError, setShowError] = useState(false);

Jsx Güncelle

showError state’i true olursa yazdığım modalın açılacağını gösterdiğim yer.

{showError && <div className="error">{isError}</div>}

BlogPost.css Güncelle

Bu modal için BlogPost.css’e aşağıdaki kodları ekleyelim.

.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;
}

Modal Açıp Kapama Fonksiyonu

Bu fonksiyon kendisine bir info bildirimi alır ve setIsError ile isError state’ini günceller.

Modal’ın görünürlüğünü sağlamak için showError state’ini true yapıyoruz.

5 saniye sonra tekrar false olarak güncelliyoruz. False olduğunda bildirim ekrandan kaybolacak.

const openMessageModal = (info) => {

        setIsError(info);
        setShowError(true);
        setTimeout(() => setShowError(false), 5000);
}

loadPosts Fonksiyonu Güncelle

loadPosts fonksiyonu içinde error ile alakalı güncellemelerimizi ekleyelim.

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!');
        }
    };

setIsLoading(true);: İlk olarak, verilerin yükleniyor olduğunu belirten setIsLoading(true) çağrısı yapılır. Bu, kullanıcıya verilerin alındığı sırada bir yükleme göstergesi gösterilecektir.

const response = await fetch('https://jsonplaceholder.typicode.com/posts');: fetch fonksiyonu ile belirtilen URL’den veri alınmaya çalışılır. await ifadesi, fetch işleminin tamamlanmasını bekler.

if (response.ok) {: Aldığımız cevap (response) başarılı ise, yani HTTP durumu 200 ise, bu bloğa girilir.

const data = await response.json();: Başarılı bir şekilde alınan cevaptan JSON formatındaki veriyi çözerek data adlı değişkene atarız.

setPosts(data);: Çözülen veriyi, component’ın state’indeki posts değişkenine atarız. Böylece, bu veri daha sonra component’ta kullanılabilir.

setIsLoading(false);: Veri alımı tamamlandıktan sonra, yükleme durumunu false olarak güncelleriz, çünkü artık yükleme işlemi bitmiştir.

if (data.length === 0 ? setIsData(false) : setIsData(true));: data dizisinin uzunluğunu kontrol ederek, eğer veri yoksa setIsData(false) çağrısını yapar, aksi takdirde setIsData(true) çağrısını yapar. Yani, eğer veri varsa isData durumunu true yapar, yoksa false.

openMessageModal(${data.length} posts found);: Veri alımı başarılı olduysa, bir modal penceresi açarak kaç adet blog yazısı bulunduğunu kullanıcıya gösterir.

} else {: Eğer cevap başarılı değilse, yani HTTP durumu 200 değilse, bu bloğa girilir.

setIsLoading(false);: Yükleme durumunu false olarak güncelleriz, çünkü hata durumu oluştuğunda da yükleme işlemi tamamlanmış olur.

setIsData(false);: Veri olmadığını belirten setIsData(false) çağrısını yaparız.

openMessageModal('There was an error!');: Hata mesajını belirleyip, kullanıcıya bir hata olduğunu bildiren bir modal penceresi açarız.

} catch (error) {: try bloğu içinde herhangi bir yerde hata olursa, bu bloğa geçilir.

setIsData(false);: Hata durumunda setIsData(false) çağrısı yaparız, çünkü veri alımı başarısız olduysa veri de yok demektir.

openMessageModal('There was an error!');: Hata mesajını belirleyip, kullanıcıya bir hata olduğunu bildiren bir modal penceresi açarız.

};: Fonksiyonun sonunu işaretler.

Uygulama Test

Bir sonraki yazımda görüşmek üzere.


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