3- ReactJS Eğitimi – Ekran Yönlendirme, State (durum) Nedir? State Yönetimi.

ReactJS Eğitim serimizin üçüncüsü ile devam ediyoruz.

Eğitim Künyesi

  • Klasör yapısı düzenlemeleri
  • Componentleri farklı dosyalardan import etme
  • State (durum) nedir? Ekranda state yönetimi

Detay Ekran Componentlerinin Oluşturulması

Bir önceki derste kişiler listesini ekrana yazdırmıştık. Bu dersimizde listleme kısmında yazdırmadığımız detay bilgilerin farklı ekranda gösterimi üzerinde çalışacağız.

Klasör Yapısının Düzenlenmesi

Bir önceki derste App.js içerisinde yaptığımızı geliştirmeleri biraz daha parçalayalım. Bu parçalama işlemi ile birlikte bir yandan da projenin klasör yapısını düzenliyor olacağız. src klasörü altında aşağıdaki gibi klasörler oluşturalım.

  • src
    • components
      • Header
    • pages
      • UserList
      • UserDetail

İlk olarak, App.js içerisinden Header componenti src/components/Header klasörü içerisine index.js isimli bir dosya oluşturup aşağıdaki içine alalım.

Sonrasında App componenti içerisinde return ifadesi içerisinde yer alan kodları, src/pages/UserList klasörü içerisinde yer alan index.js dosyasına alalım

Bu aşamada dikkat ettiyseniz eğer Header componentimizi artık components klasörü altında yer alan ayrı bir klasör altından import ediyoruz. Detay ekranımızı oluştururken de Header componentimizi bu şekilde import edip reusable component olarak konumlandıracağız.

Şimdi de UserList componentini içi boşalan App componenti içerisine yerleştirelim.

Klasör düzenleme işleminin son aşaması olarak users listesini ayrı bir dosyadan ortak kullanıma hazır hale getirmesi kaldı. Bunun için de src klasörü altında şimdilik data.js isimli bir dosya oluşturup listemizi hem UserList hem de yeni oluşturacağımız detay ekranında buradan çekeceğiz.

users listesinin data.js içerisinden export edilmesi
users listesinin data.js dosyaından import edilerek UserList componenti içerisinde kullanımı

Klasör düzenlemelerimiz şimdilik bu kadar. Bu düzenlemeler ekran çıktımızda herhangi bir değişikliğe sebep olmayacak. Bundan sonra yapacağımız geliştirmelere zemin oluşturmuş olacak.

Eğer tüm adımları tamamladıysak browser çıktımız aşağıda yeraldığı şekilde önceden tasarladığımız gibi olmaya devam edecektir

Liste Componenti Üzerinden Detay Ekrana Ulaşma

Klasörlerle ilgili düzenleme işlemimiz tamamlandığına göre detay ekranını oluşturmaya başlayabiliriz.

İlk, static olarak hangi alanların olacağını belirtelim. src/pages/UserDetail/index.js dosyasını aşağıdaki gibi dolduralım.

import React from 'react';

const UserDetail = () => {

    return(
        <>
            <b>Name: </b> Mehmet Yılmaz <br/>
            <b>Title: </b> Lead Software Developer <br/>
            <b>City: </b> İstanbul <br/>
        </>
    );
}

export default UserDetail;

Sonrasında App.js içerisinde import edelim.

import React from 'react';
import './app.scss';
import UserList from './pages/UserList';
import UserDetail from './pages/UserDetail';


function App() {
  return (
    <div className="App">
      <UserList />
      <UserDetail />
    </div>
  );
}

export default App;

Çıktımız aşağıdaki gibi olacaktır.

Bundan sonraki aşamada alt kısıma yerleştirdiğimiz detay ekranına liste ekranında seçtiğimiz kişinin bilgilerini getirme işlemi yapacağız. Ancak bu işlemi yapmadan önce state kavramından bahsetmek gerekiyor.

React State Nedir?

React dünyasında state, ekran üzerinde bulunan bileşenlerin birbirleriyle olan etkileşimleri sonrası gerçekleşen durum değişikliklerine denir.

Örneğin; Bir textbox vasıtasıyla girilen değerin ekranda anlık olarak gösterilmesi isteniyorsa, giriş yapıldıktan sonra ekranın stateinin yani durumunun değişmesi gerekir. Ekranda hiç bir şey yokken birden kullanıcı tarafından veri giriliyor ve ekran boş durumdan metin olan versiyonlu durumuna geçmiş oluyor. İşte biz bu işleme state (durum) değişikliği diyoruz.

Bir görsel ile anlatacak olursak…

State için vereceğimiz ikinci örnek üzerinde çalıştığımız konu olacak.

Bizim örneğimizde App componenti içerisinde iki adet component yer alıyor. UserList ve UserDetail. Senaryoya göre kullanıcı listeden bir kişi ismine tıklayacak ve alt kısımda o kişiye ait detaylar yer alacak.

Şimdi birlikte örneğimizdeki state değişikliğini inceleyelim.

Şimdi kullanıcının ekrandan bir kişi seçip tıklama işlemi bir input. Sonrasında detay ekranda kişi bilgilerinin görüntülenmesi işlemi de input sonra gerçekleşen durum değişikliği. Ekranımda hiç kişi detayı yok iken ya da başka bir kişinin detay var iken tıklama sonrası alt bölümdeki ekran içerisinde bilgiler ile ya hiç görünmüyorken görünecek ya da görünmesine rağmen içerisindeki bilgiler değişecek.

Daha ne olsun! Ekranda baya bir render işlemi yani state değişimi olacak 🙂

Kolları sıvayalım…

İlk önce liste öğelerimizi tıklanılabilir hale getirip tıklama eventini yakalayıp yakalayamadığımızı alert ile test edelim. UserList.js dosyamızıdaki değişiklik aşağıdaki gibi olacak

import React from 'react';
import Header from '../../components/Header';
import { users } from '../../data';

const UserList = () => {
    return (
        <>
            <Header title="First Screen Application - Users" />
            <aside>
                <ul>
                    {
                        users.map(i =>
                            <li>
                                <button 
                                    onClick={() => alert(i.name)}
                                >
                                    {i.name} {i.surname}
                                </button>
                            </li>)
                    }
                </ul>
            </aside>
        </>
    );
}

export default UserList;

Şimdi de tıklama işleminin App.js’de yakalanabilmesi için props kullanarak fonksiyon transferi yapalım.

UserList componenti içerisinde, buton kısmında alert yerine aşağıdaki gibi bir değişiklik yapalım.

<button 
	onClick={() => props.onSelectUser(i)}
  >
    {i.name} {i.surname}
</button>

App.js içerisinde onSelectUser fonksiyonunu yazalım.Test etme amaçlı yine alert kullanabiliriz.

import React from 'react';
import './app.scss';
import UserList from './pages/UserList';
import UserDetail from './pages/UserDetail';


function App() {
  return (
    <div className="App">
      <UserList onSelectUser={ (i) => alert(i.name)} />
      <UserDetail />
    </div>
  );
}

export default App;

Burada biraz kafalar karışmış olabilir. İşlemlerin tekrar üzerinden geçelim…

Liste öğelerini tıklanabilir yaptık. Tıklama işlemi bizim için bir tetikleme olayı olduğu için ve tetikleme işlemi sonrası App componentinde state değişikliği gerçekleşeceğinden tıklama işlemini App componentine taşımış olduk. UserList componenti içerisinde gerçekleşen tıklama işlemi seçilen user bilgisi ile birlikte props vasıtasıyla gönderilen fonksiyona aktarılıyor. Props ile gönderilen fonksiyon App componenti içerisinde tanımlandığı için tıklama eventini App içerisinden yakalayabiliyoruz. Burada App parent, UserList ise child component oluyor aradaki köprüyü props sayesinde kurmuş oluyoruz.

Şimdi click işlemi ile birlikte ekranda gerçekleşecek değişiklikleri yapalım.

React’da state ile işlem yapmak için state değişikliğine sebep olacak datayı tanımlamlamak gerekiyor. Aşağıda yer alan komut ile statemizi tanımlıyoruz.

const [ selectedUser, setSelectedUser ] = React.useState(null);

Burada dikkat edilmesi gereken hususlar var.

Öncelikle React.useState metodu yazılışından da anlaşılacağı üzere React dünyasına özgü bir metoddur. Bu metod sayesinde state objesinin içerisinde hangi değerler yer alacağını set edip set ettiğimiz değerleri view katmanında kullanabiliyoruz.

useState metodu dönüşünde array tipinde bir değer alır. Array içerisinde veriyi tutan obje ve bu veriyi değiştirmemize yarayan bir de fonksiyon bulunur.

Biz array içerisinde yer alan değerleri [ selectedUser, setSelectedUser ] kullanımı ile array içerisinden çıkarıp verdiğimiz isimlerle sabit olarak tanımlamış olduk. Köşeli parantez ile bu şekilde array içerisinden değerleri çıkarıp kullanma işlemine array destructuring deniyor. ES6 ile gelen bir özelliktir.

Eğer bu şekilde kısa yoldan kullanmasaydık aşağıdaki şekilde kullanmamız gerekecekti.

const arrayFromState = React.useState(null);
const selectedUser = arrayFromState[0];
const setSelectedUser = arrayFromState[1];

Önceden de bahsettiğim gibi ekran değişikliklerimizin orkestrasyonunu yapacacak olan componentimiz App olacağı için state ile ilgili işlemlerimizi de bu component içerisinde yapmamız gerekecek.

Adım adım ilerleyelim.

İlk olarak state tanımımızı App fonksiyonumuzun içerisine yazalım.

const [ selectedUser, setSelectedUser ] = React.useState(null);

Sonrasında tıklama işlemini yakaladığımız yerde seçilen kullanıcıyı state objemize setSelectedUser fonksiyonu ile yazalım.

<UserList onSelectUser={ (user) => setSelectedUser(user)} />

Sonrasında da UserList componentini eğer seçili bir kullanıcı varsa gösterip props vasıtasıyla seçilen user nesnesini içine gönderelim

{selectedUser && <UserDetail user={selectedUser} />}

App.js dosyasındaki son durum bu şekilde olacaktır.

import React from 'react';
import './app.scss';
import UserList from './pages/UserList';
import UserDetail from './pages/UserDetail';


function App() {

  const [ selectedUser, setSelectedUser ] = React.useState(null);

  return (
    <div className="App">
      <UserList onSelectUser={ (user) => setSelectedUser(user)} />
      {selectedUser && <UserDetail user={selectedUser} />}
    </div>
  );
}

export default App;

Çıktımıza baktığımızda alt tarafta yer alan detay kısmının kaybolduğunu göreceksiniz. Bunu sebebi selectedUser objesinin başlangıçta null olarak konumlanması ve view kısmında {selectedUser && } bu kontrolle eğer seçilen kullanıcı null değilse göster dediğimiz içindir.

Herhangi bir kullanıcıya tıkladığımızda selectedUser nesnesi dolacak ve ekran durumu değişip detay componentimiz görüntülenmeye başlayacaktır. Biz setSelectedUser fonksiyonunu çağırdığımızda sadece state içerisine veri yazmış olmuyoruz bir yandan da ekranın güncellenmesi için bir render işlemi başlatıyoruz.

setSelectedUser fonksiyonunu kullanmadan selectedUser = user şeklinde direk atama yapmaya çalışsaydık değişikliklerin ekrana yansımasını sağlayamamış olacaktık.

Şimdi de UserDetail componentine props vasıtasıyla gönderilen user nesnesini karşılayarak ekranda görüntülenmesini sağlayalım.

import React from 'react';

const UserDetail = (props) => {

    const { user } = props;

    return(
        <>
            <b>Name: </b> {user.name} {user.surname} <br/>
            <b>Title: </b> {user.title} <br/>
            <b>City: </b> {user.city} <br/>
        </>
    );
}

export default UserDetail;

Burada da görüldüğü üzere fonksiyon parametre olarak props isimli bir obje alıyor. Bu objede dışarıdan gönderilen iç objeler mevcut. Bizim örneğimizde user nesnesi gönderiliyor.

const { user } = props;

Kodu ile dışarıdan gönderilen user objesini ES6’ın faydalarını kullanarak çıkarıyorum. Bu işleme de object destruction işlemi deniyor.

Return ifadesi içerisinde de user nesnesinin içerisinde yer alan alanları ekrana yazdırıyorum. Böylelikle UserList içerisinde seçilen her bir kişinin detayını UserDetail içerisinde göstermiş oldum.

Zor konuyu atlattığımıza göre biraz stillendirme işlemleri ile kafa dağıtalım.

Üst kısımdaki kişi listesine buton eklediğimiz için biraz tasarımı tuhaflaştı. Ayrıca detay ekranı için özel olarak çalışmadık.

İlk önce kişi seçimini güzelleştirelim. Bunun için app.scss içerisinde daha önceden liste öğesi li için yazdığımız kısmı aşağıdaki gibi revize edelim

li{
        margin-bottom: 5px; color: $header-bg-color;
        
        button{
            display: block;
            border: none;
            min-width: 150px;
            text-align: left;
            background-color: $header-bg-color;
            color: white;
            padding: 10px;
            cursor: pointer;

            &:hover{
                background-color: $header-border-color;
            }
        }

    }

Bu değişiklikten sonra butonlar aşağıdaki gibi değişiecektir.

UserDetail için de componentin içerisinde en üst kısımda bulunan <></> taglerini div ile değiştirip className özelliğine user-detail verelim

<div className="user-detail">
            <b>Name: </b> {user.name} {user.surname} <br/>
            <b>Title: </b> {user.title} <br/>
            <b>City: </b> {user.city} <br/>
 </div>

user-detail classının içini de app.scss dosyası içerisinde dolduralım

.user-detail{
    list-style: circle;
    border: dashed 1px $header-border-color;
    padding: 10px;
}

Bu değişiklikle birlikte ekran çıktığımız bu şekilde olacaktır

Stillendirme ile birlikte konumuzun sonuna gelmiş bulunmaktayız.

Bu dersimizde geliştirdiğimiz kodlara linkten ulaşabilirsiniz.

Dilerseniz aşağıda çalışan halini gözlemleyebilirsiniz.

Bir sonraki dersimize erişmek için -> ReacJS ile Sayfalar Arası Yönlendirme

Sevgi ve sağlıkla kalın 🙂

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.