İçeriğe git
food fishing sea mountains

Devextreme Datagrid – React Datagrid’in tüm verilerini çekmek

Gökhan Duman

Zaman zaman önyüz tarafında yığın data gösterimine ihtiyaç duyarız. Bu işlemi tablo elementi ile yaptığımızda verinin büyüklüğüne bağlı olarak performans sorunları yaşayabiliriz. Hem performans sorunun üstesinden gelmek hem de ek olarak verileri filtrelemek, parça parça çekmek gibi gereksinimlerimizi karşılamak için 3. parti kütüphanelere başvurduğumuz olur. DevExpress firmasının Devextreme kütüphanesi mevzubahis durumlar için en çok kullanılan kütüphanelerden biridir.

Bu yazımda Devextreme’in React kullanımında doğabilecek sorunlarından birine değineceğim. Bildiğimiz üzere React veri kontrolünü state yapısı ile gerçekleştirir. Fakat Devextreme kütüphanesi bunun sınırla kalmaz, hem kendi içinde verileri tuttuğu bir yapı vardır hem de firmanın sürüyle genelde parça parça veri çekmek ve isteklere filtre eklemek için kullanabileceğimiz datasource‘ları vardır. Eğer Devexteme ait Datagrid’i kullanıp Datagrid’in içinden veri çekecekseniz kullandığınız yönteme bağlı olarak veri çekerken sorun yaşayabilirsiniz. Şimdi bununla alakalı bir senaryo oluşturup, çözüm yollarını inceleyelim.

Devextreme Datagrid React Kurulumu

Hızlıca bir react uygulaması kurup Devextreme Datagrid’i entegre edelim.

npm create vite@latest
install react

Sonrasında main.jsx dosyasını temizleyip, devextreme’in css dosyasını dahil edelim.

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'

// DEVEXTREME
import 'devextreme/dist/css/dx.light.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

Benzer işlemi App.jsx için de yapalım.

import { Button } from "devextreme-react";
import "./App.css";

function App() {
  return (
    <>
      <Button text="Click me" onClick={(val) => console.log(val)} />
    </>
  );
}

export default App;

App.css dosyasını da aşağıdaki gibi sadeleştirelim:

#root {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
}

Projeyi derlediğimizde aşağıdaki gibi bir buton çıkacak ve Devextreme kütüphanesinin kurulumunu bitirmiş olacağız.

devexreme install success 1

Senaryo ve Varsayılan Verinin Oluşturulması

State bağımlı olmadan (uncontrolled yapı) oluşturulan verilerin bulunduğu Datagrid bileşeninde içerisindeki verileri alırken çıkabilecek sorunları incelemek için sahte veri üretecek bir fonksiyon yazalım.

  // PRODUCT SAMPLE DATA
  const productList = useMemo(() => {
    return [...Array(1000).keys()].map((itm) => ({
      id: itm + 1,
      title: `Product ${itm + 1}`,
      price: Math.floor(Math.random() * 100),
    }));
  }, []);

Yukarıdaki fonksiyonda id, title ve price alanlarına sahip bir ürün listesi verisi oluşturduk. Olası değişikliklerde render sonucu oluşabilecek olumsuzlukların önüne geçmek içinse useMemo hook’unu kullandık.

Devextreme Datagrid Bileşeninin Dahil Edilmesi

Daha önce kütüphanenin düzgün yüklenip yüklenmediğini test etmek için Button bileşenini çağırmıştık. Şimdiki adımda 1000 satırlık bir veriyi gösterecek bir veri tablosu çağıracağız.

Veri tablosu için Devextreme’nin Datagrid bileşenine başvuracağız. Datagridde ise performansı arttırmak için virtual scrolling, veri işlemleri için editing özelliğini dahil edeceğiz. Aşama aşama gidecek olursak:

Datagrid Virtual Scrolling için Stiller

Datagrid kullanırken Infinite Scrolling ya da Virtual Scrolling kullanıyorsanız, Datagrid bileşeninin sabit yükseklikte bir div elementinde bulunması ve bulunduğu div elementinin içerik taşırmaması gerekir.

Bu koşulları sağlamak için App.css dosyasına grid-wrapper sınıfını ekleyip kullanabiliriz.

.grid-wrapper{
  height:calc(100vh - 200px);
  position: relative;
  overflow: hidden;
}

Datagrid Bileşeninin Dahil Edilmesi

Gerekli hazırlıkları yaptığımıza göre Datagrid bileşenini ve bileşende kullanacağımız Scrolling, Editing özelliklerini dahil edebiliriz. Bu kısımda ek olarak toolabar’a kaydet butonu iliştireceğimiz için Toolbar bileşenine de ihtiyacımız bulunmaktadır.

// DEVEXTREME
import { Button } from "devextreme-react/button";
import DataGrid, {
  Editing,
  Item,
  Scrolling,
  Toolbar,
} from "devextreme-react/data-grid";

Gerekli kütüphaneleri dahil ettiğimize göre App.js dosyasında kapsayıcı div ile beraber Devextreme bileşenlerini çağırabiliriz.

<div className="grid-wrapper">
        {/* DATAGRID */}
        <DataGrid
          dataSource={productList}
          rowAlternationEnabled={true}
          showBorders={true}
          width="100%"
          height="100%"
        >
          {/* TOOLBAR */}
          <Toolbar>
            {/* SAVE BUTTON */}
            <Item location="before">
              <Button icon="save" type="default" stylingMode="contained" />
            </Item>
            {/* NEW ROW BUTTON */}
            <Item name="addRowButton" />
          </Toolbar>
          {/* EDITING */}
          <Editing
            allowUpdating={true}
            allowAdding={true}
            allowDeleting={true}
            mode="cell"
          />
          {/* VIRTUAL SCROLLING */}
          <Scrolling mode="virtual" />
        </DataGrid>
      </div>

Bu adımdan sonra ekranımız aşağıdaki gibi olacaktır.

grid first render 1

Bu ekranımızda artık oluşturuğumuz ürün verilerinin görüntüleme, ekleme, düzenleme ve silme işlemlerini yapabiliriz. Peki ya verilerin son halini almak istersek?

Örneğimizde oluşturduğumuz Datagrid bileşeni uncontrolled yapıda olduğu için bileşene referans atayıp, referans üzerinden verileri almamız gerekiyor.

 // GRID REF
  const gridRef = useRef(null);

Yukarıdaki gibi useRef hook’u ile referans objesi oluşturabiliriz. Oluşturduğumuz referansı aşağıdaki gibi Datagrid bileşenine ekleyebiliriz.

<DataGrid
          ref={gridRef}
...

Datagrid Verilerini Yazdırmak

Verilerimiz ve Datagrid bileşenimiz hazır olduğuna göre artık consol’a yazdırma işlemini gerçekleştirebiliriz.

  const printGridData = () => {
    const gridInstance = gridRef.current?.instance;
    const gridItems = gridInstance?.getDataSource()?.items();
    if (Array.isArray(gridItems)) {
      console.log("Array.length: ", gridItems.length);
      console.table(gridItems);
    }
  };

Yukarıda Datagrid’e verdiğimiz gridRef referansı ile bileşenin Datasource’una ulaşıp verilerini alabiliriz. Şimdi de yazdığımız pringGridData fonksiyonunu kaydet butonuna bağlayalım.

 {/* SAVE BUTTON */}
            <Item location="before">
              <Button
                icon="save"
                type="default"
                stylingMode="contained"
                onClick={printGridData}
              />
            </Item>

Uygulamanın bu haliyle kaydetme butonuna tıkladığımızda aşağıdaki gibi bir sonuç alarız:

console log print 1 1

Yukarıda gördüğümüz gibi 1000 verimiz olmasına rağmen sadece ilk 60 veriyi yazdırdı. Başta belirttiğim gibi Infinite ve Virtual scrolling modellerini kullanırsanız karşılaşağınız tablo bu şekilde olacaktır. Standart modu kullandığınızda da tüm ögelerin görüntülenmesi için paging değerini veri sayısından büyük eşit tutmanız gerekmektedir. Tabi bu da beraberinde performans sorunları getirebilir. Bu nedenle tüm verileri nasıl alabileceğimize bakalım.

 const printGridData = async () => {
    const gridInstance = gridRef.current?.instance;
    // const gridItems = gridInstance?.getDataSource()?.items();
    const gridStore = gridInstance?.getDataSource()?.store();
    const loadedGridItems = await gridStore?.load();
    if (Array.isArray(loadedGridItems)) {
      console.log("Array.length: ", loadedGridItems.length);
      console.table(loadedGridItems);
    }
  };

printGridData fonksiyonunu yukardaki gibi asenkron olacak şekilde düzeltip, Datagrid’in store’una erişebilirsek, sonrasında load fonksiyonu ile tüm verileri alabiliriz.

console print 2 1

Bu yöntemle ek olarak henüz kayıtlı olmayan verinin çekilmesi ile ilgili sonunu da aşmış olursunuz. Söylediklerimi daha da açmak gerekirse Datagrid üzerinde düzenleme yaparken hücreden çıkmadan kaydet düğmesine basarsanız, düzenlemedeki hücrenin güncel verisi yerine eski verisi yazdırılacaktır.

Bu yüzden eğer gridInstance?.getDataSource()?.items(); yöntemini kullanıyorsanız öncesinde kaydedilmemiş veri olup olmadığını kontrol etmeniz ve eğer varsa veriyi kaydetmeniz gerekmektedir.

  const gridHasEditData = gridInstance?.hasEditData();

            if (gridHasEditData) {
              await gridInstance?.saveEditData();
            }

Datagrid’in store’una erişip load yaptığımızda bu gereklilik ortadan kalkmaktadır.

Sonuç

Devextreme Datagrid bileşeninde uncontrolled yapıda verileri almak için Datagrid’e referans verip store’unu load ederek verileri çekebiliriz.

Yazıdaki örneğin kaynak kodlarına github üzerinden buraya tıklayarak erişebilirsiniz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir