Photo by Jan Canty on Unsplash

REACT

React Boundaries (Error, Suspense, Bundle, Context, Server/Client Boundaries)

React içerisinde bir çok yerde bu Boundary kavramını görüyor, duyuyoruz, Boundary nedir, Ne işe yarar ? Boundary Türleri Nelerdir ?)

5 min readJul 7, 2023

--

Yazılım geliştirmede boundaries terimi, bir yazılım uygulaması içindeki farklı bileşenler, sistemler veya etki alanları arasındaki kavramsal veya fiziksel ayrımı ifade eder. Her bir bileşenin veya sistemin sınırlarını ve sorumluluklarını tanımlayan net bir bölümü veya arayüzü temsil eder.

Yazılım geliştirmede boundaries;

Functional Boundary: Fonksiyonel sınır, bir yazılım sistemi içindeki belirli bir bileşenin veya modülün kapsamını ve sorumluluklarını tanımlar. Bu bileşenin neler yapabileceğinin ve diğer bileşenler veya sistemlerle nasıl etkileşime gireceğinin sınırlarını belirler.

System Boundary: Sistem sınırı, bir yazılım sisteminin the kenar(edge) or interface temsil eder. Farklı sistemler, hizmetler veya modüller arasındaki ayrımı tanımlar ve bunların birbirleriyle nasıl iletişim ve etkileşim kuracaklarını belirtir.

Security Boundary: Güvenlik sınırı, yazılım tasarımı ve mimarisinde güvenilen ve güvenilmeyen bileşenleri veya sistemleri ayıran koruyucu bir önlemdir. Erişim kontrollerini uygulayarak ve yetkisiz erişimi önleyerek hassas verilerin ve işlemlerin güvende tutulmasını sağlar.

Data Boundary: Veri sınırı, bir yazılım uygulaması içindeki veri akışı için sınırları ve kuralları tanımlar. Verilerin farklı bileşenler veya sistemler arasında nasıl iletileceğini, depolanacağını, doğrulanacağını ve dönüştürüleceğini belirler ve veri tutarlılığını, bütünlüğünü ve gizliliğini sağlar.

Process Boundary: Süreç sınırı, bir yazılım uygulaması içindeki farklı süreçler veya iş parçacıkları arasındaki ayrımı temsil eder. Her bir sürecin izole bir şekilde çalışmasını sağlar ve eş zamanlı süreçler arasındaki etkileşimi veya çatışmaları önler.

Interface Boundary: Arayüz sınırı, iki bileşen veya sistem arasındaki anlaşmayı tanımlar. Verilerin, komutların veya isteklerin nasıl yapılandırılacağını, biçimlendirileceğini ve giden/gelen verinin yapısını belirleyerek yazılımın farklı bölümleri arasında birlikte çalışabilirliği ve entegrasyonu sağlar.

Yazılımdaki sınırlar(boundaries) encapsulation, modülerlik, güvenlik, sürdürülebilirlik ve ölçeklenebilirlik gibi çeşitli amaçlara hizmet eder.

Karmaşık sistemlerin düzenlenmesine sağlar, yani birbirinden farklı yapılara bölerek (separation of concerns) yapıları ele alırki bu sayede kendi içerisinde birbirine benzer kısımları daha kolay kontrol edebilir, farklı bileşenleri, yazılımları ve sistemleri birbirleri arasındaki iletişimleri belirleyip daha kolay çalışmasını sağlatabilirsiniz.

React Boundary Kavramı

React bir rendering kütüphanesi, ve günümüzde biraz daha etki alanını genişleterek Next, Remix, Gatsby veya 3rd Party kütüphaneler ile birleşerek uygulamaları oluşturan bir Meta Framework dönüştü. React’ı anlamak için nasıl

Bileşen Modelini(Component Modeli) anlamız, Bileşenlerin Composition yaparak birbirlerini kapsadığını anlamamız gerekiyorsa, Kod paylaşımı için util library kod paylaşırken, state kod paylaşımları için Hook yapılarını anlamamız gerekiyorsa, aynı şekilde React Boundary konusunuda iyi anlamız gerekiyor

React’da bileşenlerin, kod akışının, kodun çalışma yerinin belli nedenlerden dolayı ayrıştırılması gerekir. Bunun için React Boundary kullanılır (Biz bunları her ne kadar Composition gibi görsekte aslında bunlar React’ın son kullanıcıya göstermeden(DX) farklı konsept ve çalışma şekillerini ayrıştırmasıdır.

Buna benzer yapıları React Digital Garden (onurdayibasi.dev) sitesinin Routing oluştururken kullandım.

Make React Apps More Dynamic

React Boundary Türleri

Error Boundary:

React ekrana çizim yaparken(rendering aşamasında) bir hata oluşursa bu durumda ekranı bembeyaz, veya simsiyah bir şekilde görürsünüz. Burada React’ın sağladığı Error Boundary kullanarak bu durumda oluşan durumları yakalamayı sağlayabilirsiniz.

Bu kısımdaki bileşenlerde hatayı yakalamak istediğiniz durumda bunu ErrorBoundary ilgili Bileşeni kapsamalıyız.

<ErrorBoundary fallback={<p>Something went wrong</p>}>
<Profile />
</ErrorBoundary>

Buradaki ErrorBoundary React.Component türettiğimiz bir sınıf içerisinde aşağıdaki Sınıfın gerçekleştirimi ile olur.

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}

componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error, info.componentStack);
}

render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return this.props.fallback;
}

return this.props.children;
}
}

Bu kod içerisindeki bir bileşenin render sonucu hata almasını aynı ExceptionHandling try, catch yapısı ile yakalayıp, bize ekranda Fallback olarak bileşenin render edilmesine ve boş beyaz ekran gösterilmesini engeller.

Suspense Boundary:

React içerisinde o bileşenler üzerinde Async bir işlem yapıldığı durumlarda bileşenin bekleme durumunda bir takım geribildirim bileşenleri ile bu kısımda Async bir işlem yapıldığını anlatmak için kullanılır.

import { Suspense } from 'react';

function App() {
return (
<div>
<h1>My App</h1>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}

Context Boundary:

React bileşenlerin ortak bağlam(context) verileri tutup bileşen ağacı boyunca bunları paylaşabilmesi için Context API’si sunar. Birçok kütüphane bu Context API’sini kullanarak (ReactRouter, Redux, ReactQuery, ApolloClient) ortak bağlamlarını bileşenler üzerinde tek tek props aktarımı yapmadan erişim yapabilmesini sağlar.

// Create a context object
const MyContext = React.createContext();

// Create a provider component
function MyProvider({ children }) {
const sharedData = "This is shared data";

return (
<MyContext.Provider value={sharedData}>
{children}
</MyContext.Provider>
);
}

// Component consuming the context
function MyComponent() {
return (
<MyContext.Consumer>
{value => <div>{value}</div>}
</MyContext.Consumer>
);
}

// Usage
function App() {
return (
<MyProvider>
<MyComponent />
</MyProvider>
);
}

Not: Provider Pattern konusunda detaylara erişmek için daha önceden yazmış olduğum React Kütüphanelerinde Provider Pattern Kullanımı blog yazımı okuyabilirsiniz.

Server/Client Boundary (React Server Components):

React bu kısımda bileşenleri 2 kısma ayırıyor. Bir Client yani eskiden beri kullandığımız UI oluşturmada kullanılan bileşenler, bir diğeri herhangi bir sunucu/vb yerde çalışan Data Fetching odaklanmış, DB ve Cache yapıları ile iletişim kurup sunucu tarafında bileşen yapıları oluşturabilmenizi sağlayan Sunucu bileşenleri, aşağıdaki resimde örneğin Bileşen ağacının karışık bir şekilde Server(Turuncu) ve Client(Mavi) bileşenlerden oluştuğunu görebilirsiniz.

Next.JS aldığım bir örnekte use client veya , dosya isminde client, server ayrımı ile dosyalar üzerinden bileşenlerin türlerinin ayrışımının yapılması sağlanacak

'use client'

import { useState } from 'react'

export default function Counter() {
const [count, setCount] = useState(0)

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
)
}

Tabiki Server / Client Component ’lar aynı yeteneklere ve özelliklere sahip değil Next.JS aldığım aşağıdaki ekran görüntüsünde iki farklı bileşen türünün birbirlerinin yaptığı şeyleri yapamadığını görebilirsiniz.

https://nextjs.org/docs/getting-started/react-essentials#client-components

Örneğin ClientSide Interactivity, WebAPI, useState/useEffet varken, Server Component fetch data, veri API üzerinden veritabanına Cache erişim yetenekleri bulunur.

React Boundary bu bileşenleri birbirinden ayırması gerekir.

Bundle Boundaries

Bundle Boundaries, Webpack, Vite vb… bundle araçlarına React’ın bu JS parçasını ayrı ayrı load edeceğim diyerek bunları parçalara ayırması ve performansı, network giden gelen JS parçalı şekilde çalışabilmesi sağlayan Boundary’ dir

const MyComponent = React.lazy(() => import('./MyComponent'));

Bu işlemleri yaparken yukarıda bahsettiğimiz diğer Suspense, ErrorBoundary bu yapıları sarmallayabilir, Fakat burada bu React.lazy() bundling aracına bu JS dosyasını veya buna bağlı bağımlılıkları ayrı parçalara bölebilmesi için göstergede bulunur.

LearnReactUI.dev

React Ekosisteminde kendi kariyerinizi daha ileriye götürmek için LearnReactUI.dev sitesine üye olmayı unutmayın. Bu site piyasada çalışan(real-world) Web Uygulaması geliştirmek isteyen React geliştiricileri için oluşturulmuş bir web sitesidir.

LearnReactUI.dev

Referanslar

--

--