NextJS ve ChartJS Kullanarak Gerçek Zamanlı Veri Görselleştirme

Fatih Küçükkarakurt

Fatih Küçükkarakurt

Veri görselleştirme hakkında konuştuğumuzda, hemen akla gelen şey, verileri görsel bir biçimde sunmaya yardımcı olan analitik veya istatistiksel grafiklerdir. Gerçek zamanlı teknolojileri kullanarak, veriler değiştikçe görselleştirmeyi güncellemek mümkün hale gelir. Neredeyse her veri analizi hizmeti gerçek zamanlı veri görselleştirme sağladığından bu artık yeni bir şey değil. Bununla birlikte, yeni teknolojiler ortaya çıktıkça, gerçek zamanlı veri görselleştirme deneyimleri oluşturmanın daha yeni yolları ortaya çıkıyor.

Bu makalede, bir anketten aldığımız verilere dayanarak çok basit bir gerçek zamanlı veri görselleştirme uygulaması oluşturmaya çalışacağız.

İçerik

Ön Koşullar

Başlamadan önce, makinenizde Node ve npm veya yarn'ın kurulu olduğundan emin olun. İşte kullanacağımız temel teknolojiler:

  1. Next.js - Sunucu tarafında oluşturulan (SSR) React uygulamalarını kolaylıkla oluşturmak için kullanılan bir çerçevedir. SSR React uygulamaları oluşturmanın getirdiği zorlukların çoğunun üstesinden gelir.
  2. Pusher - Pusher, push bildirimleri ve pub/sub mesajlaşma gibi farklı gerçek zamanlı ihtiyaçlara sahip uygulamalar oluşturmak için kullanılan bir teknolojidir. Veri görselleştirme uygulamamızın gerçek zamanlı yeteneğinin arkasındaki motordur.
  3. Chart.js - Chart.js, programlanabilir bir arayüz aracılığıyla farklı veri görselleştirme çizelgeleri oluşturmayı mümkün kılan basit ancak esnek bir JavaScript grafik kitaplığıdır.
  4. React - Bileşen tabanlı bir mimari kullanarak ölçeklenebilir web uygulamaları oluşturmak için çok popüler bir JavaScript DOM oluşturma çerçevesidir.
  • Tüm bunlara ek olarak örnek projemizde bir kaç farklı kitaplık daha kullanacağız. Bunları aşağıda görmüş olacaksınız. Ama tüm bunlardan önce cihazınızda lütfen Node'un yüklü olduğundan emin olun.

Bağımlılıkları Yükleme

Uygulama için yeni bir dizin oluşturun ve gerekli bağımlılıkları yüklemek için aşağıdaki komutu çalıştırın.

# Yeni bir klasör oluşturun
mkdir realtime-visualization-app  

# Oluşturduğunuz bu klasörün içine girin
cd realtime-visualization-app  

# Gerekli bağımlılıkları yükleyin
npm init -y  
npm install react react-dom next pusher pusher-js chart.js react-chartjs-2
npm install express body-parser cors dotenv axios 
npm install --save-dev cross-env npm-run-all

Ortam Değişkenlerini Ayarlama

Örnek uygulamada kullanacağınız kimlik bilgilerinizi almak için Pusher Dashboard'a giderek yeni bir uygulama oluşturun.

Uygulamanızın kök dizininde, .env adında bir dosya oluşturun ve uygulama kimlik bilgilerinizi aşağıdaki gibi buraya girin.

PUSHER_APP_ID=YOUR_APP_ID
PUSHER_APP_KEY=YOUR_APP_KEY 
PUSHER_APP_SECRET=YOUR_APP_SECRET 
PUSHER_APP_CLUSTER=YOUR_APP_CLUSTER

Yukarıdaki kod parçacığında belirtilen değişken adlarının aynısını kullandığınızdan emin olun. Bunlara kodumuzun birkaç noktasında değineceğiz.

Ardından uygulamanızın kök dizininde, next-config.js adından bir yapılandırma dosyası oluşturun.

    /* next.config.js */

    const webpack = require('webpack');
    require('dotenv').config();

    module.exports = {
      webpack: config => {
        const env = Object.keys(process.env).reduce((acc, curr) => {
          acc[`process.env.${curr}`] = JSON.stringify(process.env[curr]);
          return acc;
        }, {});

        config.plugins.push(new webpack.DefinePlugin(env));

        return config;
      }
    };

Next.js'in tanımladığımız ortam değişkenlerine ve process.env nesnesine erişerek, bunları React bileşenlerimize sunacak. Bunun için yukarıda Webpack'i yapılandırıyoruz.

Başlangıç

Sunucuyu Kuralım

Bir Express uygulama sunucusunu oluşturmak için Next.js kullanarak basit bir yapı oluşturacağız. Ayrıca Express sunucu için gerekli ara yazılımları yükleyeceğiz ve ardından Pusher'ı ortam değişkenlerimize eklediğimiz kimlik bilgilerini kullanarak yapılandıracağız.

Uygulamanızın kök dizininde server.js adında bir dosya oluşturun ve sunucuyu kurmak için aşağıdaki kod parçacığını ekleyin:

    /* server.js */

    const cors = require('cors');
    const next = require('next');
    const Pusher = require('pusher');
    const express = require('express');
    const bodyParser = require('body-parser');
    const dotenv = require('dotenv').config();

    const dev = process.env.NODE_ENV !== 'production';
    const port = process.env.PORT || 3000;

    const app = next({ dev });
    const handler = app.getRequestHandler();

    // Pusher kimlik bilgilerinizin .env dosyasında doğru şekilde ayarlandığından emin olun
    // Belirtilen değişkenleri kullanın
    const pusher = new Pusher({
      appId: process.env.PUSHER_APP_ID,
      key: process.env.PUSHER_APP_KEY,
      secret: process.env.PUSHER_APP_SECRET,
      cluster: process.env.PUSHER_APP_CLUSTER,
      encrypted: true
    });

    app.prepare()
      .then(() => {

        const server = express();

        server.use(cors());
        server.use(bodyParser.json());
        server.use(bodyParser.urlencoded({ extended: true }));

        server.get('*', (req, res) => {
          return handler(req, res);
        });

        server.listen(port, err => {
          if (err) throw err;
          console.log(`> Ready on http://localhost:${port}`);
        });

      })
      .catch(ex => {
        console.error(ex.stack);
        process.exit(1);
      });

Npm Komut Dosyalarını Değiştirin

Son olarak, package.json dosyasının scripts bölümünü aşağıdaki kod parçacığı gibi görünecek şekilde değiştireceğiz:

    /* package.json */

    "scripts": {
      "dev": "node server.js",
      "build": "next build",
      "prod:server": "cross-env NODE_ENV=production node server.js",
      "start": "npm-run-all -s build prod:server"
    }

Uygulama bileşenlerimizi oluşturmaya başlamak için ihtiyacımız olan her şeyi hazırladık. Şimdi terminalinizde npm run dev komutunu çalıştırırsanız, varsayılan uygulama sunucusunu 3000 portunda başlatacaktır. Ancak, tarayıcınızda henüz bir sonuçla karşılaşmamanız çok normal. Çünkü herhangi bir dizin sayfası bileşeni oluşturmadık. Uygulama bileşenlerini oluşturmaya bu aşamadan sonra başlayalım.

Dizin Sayfasını Oluşturalım

Next.js ile çalışırken, uygulamanızın sayfa bileşenlerini pages dizininde oluşturmanız gerekir. Şimdi, uygulamamızın kök dizininde pages dizini oluşturacağız ve uygulamamızın dizin sayfası için, burada yeni bir index.js dosyası oluşturacağız.

Birden çok sayfada yeniden kullanılabilen bir düzene sahip olmak iyi bir uygulama olarak kabul edilir. Size bir tür standart metin verir ve sizi gereksiz tekrarlardan kurtarır.

Dizin sayfasına içerik eklemeden önce, uygulama sayfalarımızda standart şablon olarak kullanılabilecek bir Layout bileşeni oluşturacağız. Bunun için uygulamanızın kök dizininde bir components dizini oluşturun. Daha sonra components dizini içerisine Layout.js adında bir dosya ekleyin. Aşağıdaki kod parçacığını buraya yazayabilirsiniz.

    /* components/Layout.js */

    import React, { Fragment } from 'react';
    import Head from 'next/head';

    const Layout = props => (
      <Fragment>
        <Head>
          <meta charSet="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
          <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossOrigin="anonymous" />
          <title>{props.pageTitle || 'Realtime Data Visualization'}</title>
        </Head>
        {props.children}
      </Fragment>
    );

    export default Layout;

Sayfalarımızın <head> bölümüne meta bilgi eklemek için sadece next/head bileşenini kullanıyoruz. Ayrıca uygulamamıza biraz stil eklemek için Bootstrap CDN dosyasına bir bağlantı sağladık. Sayfa başlığını dinamik olarak prop kullanarak ayarlıyoruz ve sayfa içeriklerini {props.children} kullanarak oluşturuyoruz.

Şimdi devam edelim ve daha önce oluşturduğumuz index.js dosyasına aşağıdaki içeriği ekleyelim:

    /* pages/index.js */

    import React, { Component, Fragment } from 'react';
    import axios from 'axios';
    import Pusher from 'pusher-js';
    import Layout from '../components/Layout';

    class IndexPage extends Component {

      render() {
        return (
          <Layout pageTitle="Realtime Data Visualization">
            <main className="container-fluid position-absolute h-100 bg-light">
              <div className="row position-absolute w-100 h-100">

                <section className="col-md-7 d-flex flex-row flex-wrap align-items-center align-content-center px-5 border-right border-gray"></section>

                <section className="col-md-5 position-relative d-flex flex-wrap h-100 align-items-start align-content-between bg-white px-0"></section>

              </div>
            </main>
          </Layout>
        );
      }

    }

    export default () => (
      <Fragment>
        <IndexPage />
      </Fragment>
    );

Bootstrap tarafından sağlanan yerleşik sınıfları kullanarak bazı temel stillerle konteyner öğelerini DOM'a dönüştürüyoruz. Uygulamayı tarayıcınızda görüntülerseniz, iki <section> etiketi ile karşılaşacaksınız.

Az önce oluşturduğumuz iki <section> etiketinin her birinde bir tane olmak üzere iki bileşene ihtiyacımız olacak. İlk olarak, anketin sorusu ve cevapları için bir Poll bileşenimiz olacak. Sonra veri görselleştirme için bir Stats bileşeni oluşturacağız. Şimdi devam edelim ve Poll bileşenimizi oluşturalım.

Anket Bileşenini Oluşturalım (Poll Component)

components dizini içerisinde bir Poll.js dosyası oluşturalım ve aşağıdaki kod parçacığını buraya yazalım.

    /* components/Poll.js */

    import React, { Component, Fragment } from 'react';
    import axios from 'axios';

    class Poll extends Component {

      state = { selected: null }

      handleSubmit = evt => {
        axios.post('/answer', { choice: this.state.selected });
        this.setState({ selected: null });
      }

      render() {

        const { selected: selectedChoice } = this.state;
        const { question = null, choices = [] } = this.props;

        return (
          <Fragment>

            <span className="d-block w-100 h5 text-uppercase text-primary font-weight-bold mb-4" style={{ marginTop: -50 }}>Poll for the Day</span>

            <span className="d-block w-100 h1 text-dark">{question}</span>

            <div className="my-5 pt-0 pb-5">
              {
                choices.map((choice, index) => {

                  const handleClick = selected => evt => this.setState({ selected });

                  const selected = selectedChoice && selectedChoice === choice;

                  const labelClass = ['custom-control-label pl-5 position-relative', selected ? 'checked' : ''].join(' ');

                  return (
                    <div key={index} className="custom-control custom-radio py-3 ml-2 d-flex align-items-center">
                      <input className="custom-control-input" type="radio" name="poll-response" id={`poll-response--radio-${index + 1}`} value={choice} checked={selected} />

                      <label className={labelClass} htmlFor={`poll-response--radio-${index + 1}`} onClick={handleClick(choice)}>{ choice }</label>
                    </div>
                  );

                })
              }
            </div>

            <button type="button" className={`btn btn-primary text-uppercase my-5 ml-4 px-5 py-3 d-block ${selectedChoice ? '' : 'in'}visible`} disabled={!selectedChoice} onClick={this.handleSubmit}>Submit</button>

          </Fragment>
        );
      }

    }

    export default Poll;

Poll.js'i oluştururken, ilk önce bileşenin durumunu boş bir seçili özellik ile başlattık.

render() yönteminde, Anket bileşeni için iki props, questionve choice gerektiğini fark edeceksiniz. Soruyu basitçe işliyoruz ve ardından seçimler arasında döngü yapıyoruz, her birini seçim için özel bir radio <input> ile oluşturuyoruz.

Bir seçeneğin seçilmesi, bir onClick() olay işleyicisini kullanarak state selected özelliğini selectedChoice'a günceller. Ardından, seçilen seçimi göndermek için kullanılacak bir <button> ortaya çıkarır.

Submit butonu tıklandığında, handleSubmit() olay işleyicisini tetiklenir. handleSubmit() yöntemi, daha sonra sunucuda uygulayacağımız /answer uç noktasına bir POST HTTP isteğinde bulunur. Ayrıca state selectedözelliğini null olarak sıfırlar.

Ardından, Poll öğelerinin ek stilleri için dizin sayfasına bazı genel stiller ekleyeceğiz. Bunun için pages/index.js dosyasında aşağıdaki değişiklikleri yapabilirsiniz.

    /* pages/index.js */

    export default () => (
      <Fragment>
        <IndexPage />
        <style global jsx>{`

          .custom-control-label {
            background: transparent;
            color: #999;
            font-size: 2rem;
            font-weight: 500;
            cursor: pointer;
            line-height: 2.25rem;
          }

          .custom-control-label:before, .custom-control-label:after {
            top: 0;
            left: -10px;
            height: 2.25rem;
            width: 2.25rem;
            cursor: pointer;
            box-shadow: none !important;
          }

          .custom-control-label.checked {
            color: #007bff !important;
          }

          button.btn {
            letter-spacing: 1px;
            font-size: 1rem;
            font-weight: 600;
          }

        `}</style>
      </Fragment>
    );

İstatistik Bileşenini Oluşturalım (Stats Component)

components dizinine, Stats.js adından bir dosya oluşturalım ve aşağıdaki kod parçacığını buraya yazalım.

    /* components/Stats.js */

    import React, { Fragment } from 'react';
    import { Line } from 'react-chartjs-2';

    const Stats = props => {

      const { choices = [], stats = {} } = props;
      const counts = choices.map(choice => stats[choice] || 0);
      const totalCount = counts.reduce((total, count) => total + count, 0);

      const chartData = {
        labels: choices,
        datasets: [
          {
            lineTension: 0,
            backgroundColor: 'rgba(68, 204, 153, 0.05)',
            borderColor: 'rgba(68, 204, 153, 0.9)',
            borderWidth: 2,
            borderJoinStyle: 'round',
            pointRadius: 5,
            pointBorderColor: '#fff',
            pointBackgroundColor: 'rgba(68, 204, 153, 0.9)',
            pointBorderWidth: 3,
            data: counts
          }
        ]
      };

      const chartOptions = {
        layout: { padding: { top: 25, bottom: 75, left: 75, right: 75 } },
        maintainAspectRatio: false,
        scales: {
          yAxes: [{
            ticks: { beginAtZero: true, display: false }
          }]
        },
        legend: { display: false },
        title: {
          display: true,
          text: 'POLL COUNTS',
          padding: 10,
          lineHeight: 4,
          fontSize: 20,
          fontColor: '#677'
        }
      };

      return <Fragment></Fragment>

    };

    export default Stats;

Burada react-chartjs-2 modülünden Line'ı içe aktardığımıza dikkat edin. Bu, veri görselleştirme için çizgi grafikleri çizmemizi sağlayacaktır.

Stats bileşeni iki prop gerektirir:

  1. choices- ana bileşenden aktarılan anket seçenekleri dizisi.
  2. stats- ana bileşenden aktarılan anket seçenekleri nesnesi. Nesne anahtarları (keys) seçimlerdir, değerler (values) ise her seçimin seçilme sayısıyla eşleşir.

Anket sayılarını (poll counts), ayrı bir diziye çıkarıyoruz. Ayrıca toplam sayıyı .map() ve .reduce() dizi yöntemlerini kullanarak bir değişkende depoluyoruz.

Ardından, oluşturmak istediğimiz çizgi grafiği için datave optionsnesnelerini oluşturuyoruz. choicesdizisini grafik etiketlerimiz ve countsdizisini de grafik veri kümemiz olarak ayarladığımıza dikkat edin. Kullanılabilir grafik türleri ve seçenekler hakkında daha fazla bilgi edinmek için Chart.js Belgelerine bakabilirsiniz.

Devam edelim ve oluşturmak istediğimiz kısımları Stats.js bileşenine ekleyelim. Az önce oluşturduğunuz Stats.js bileşenini aşağıdaki gibi değiştirebilirsiniz.

    /* components/Stats.js */

    return (
      <Fragment>

        <div className="position-relative h-50 w-100 d-flex align-items-center border-bottom border-gray">
          <Line data={chartData} width={100} height={50} options={chartOptions} />
        </div>

        <div className="position-relative h-50 w-100 d-flex flex-wrap align-items-start align-content-start">

          <div className="d-flex flex-wrap w-100 text-center justify-content-center align-items-center align-content-center" style={{ height: 'calc(100% - 150px)' }}>
            <span className="d-block w-100 text-uppercase pb-2 font-weight-bold text-secondary" style={{ fontSize: '1.25rem' }}>Total Count</span>
            <span className="d-block w-100 text-dark" style={{ fontSize: '5rem' }}>{totalCount}</span>
          </div>

          <div className="w-100 d-flex justify-content-between align-items-center text-center border-top border-gray" style={{ height: 100 }}>
            {
              counts.map((count, index) => {
                const className = ['h-100 position-relative d-flex align-items-center', index > 0 ? 'border-left border-gray' : ''].join(' ');

                return (
                  <div key={index} className={className} style={{ width: '20%', fontSize: '2rem' }}>
                    <span className="d-block w-100 p-3 text-dark">{count}</span>
                  </div>
                );
              })
            }
          </div>

          <div className="w-100 d-flex justify-content-between align-items-center text-center border-top border-gray bg-light" style={{ height: 50 }}>
            {
              choices.map((choice, index) => {

                const className = ['h-100 position-relative d-flex align-items-center', index > 0 ? 'border-left border-gray' : ''].join(' ');

                return (
                  <div key={index} className={className} style={{ width: '20%', fontSize: '0.7rem' }}>
                    <span className="d-block w-100 text-uppercase p-3 font-weight-bold text-secondary">{choice}</span>
                  </div>
                );

              })
            }
          </div>

        </div>

      </Fragment>
    );

Daha önce tanımladığımız chartData ve chartOptions'ı kullanarak bir Line grafik (çizgi grafiği) oluşturuyoruz. react-chartjs-2 paketini kontrol ederek grafiğin nasıl yapılandırılacağı hakkında daha fazla bilgi edinebilirsiniz.

Ayrıca totalCount'u ve seçeneklerin her birinin sayılarını da işliyoruz. Stats bileşenimiz için tek ihtiyacımız olan bu.

Dizin Sayfası Bileşenini Tamamlayalım

Dizin sayfası bileşenini tamamlamanın zamanı geldi. Pusher'ı ayarlamamız ve bir channel'a bağlanmamız gerekecek. Ayrıca az önce oluşturduğumuz Poll ve Stats bileşenlerini de çağırmamız gerekecek. pages/index.js dizininde bulunan index bileşenini aşağıdaki kod parçacığını içerecek şekilde düzenleyebilirsiniz.

    /* pages/index.js */

    class IndexPage extends Component {

      state = { answers: {} }

      componentDidMount() {

        this.pusher = new Pusher(process.env.PUSHER_APP_KEY, {
          cluster: process.env.PUSHER_APP_CLUSTER,
          encrypted: true
        });

        this.channel = this.pusher.subscribe('poll-board');

        this.channel.bind('new-answer', ({ choice, count }) => {
          let { answers } = this.state;
          answers = { ...answers, [choice]: count };
          this.setState({ answers });
        });

        this.pusher.connection.bind('connected', () => {
          axios.post('/answers')
            .then(response => {
              const answers = response.data.answers;
              this.setState({ answers });
            });
        });

      }

      componentWillUnmount() {
        this.pusher.disconnect();
      }

      // render() metotları...

    }

Buraya kadar yaptıklarımızı özetleyecek olursak:

  1. İlk olarak state'i boş bir answer nesnesi özelliği içerecek şekilde başlattık. Bu answers özelliği, yeni cevaplar geldikçe güncellenecektir. Bileşen bağlandığında, componentDidMount() döngüsü yöntemi içinde bir Pusher bağlantısı ve bir channel bağlantısı kuruyoruz.
  2. poll-board adı verilen bir Pusher kanalına dahil olduğumuzu görebilirsiniz. Daha sonra, yeni bir cevap alındığında (new-answer), tetiklenen kanaldaki new-answer'a bağlanıyoruz. Ardından, sunucudan aldığımız güncellenmiş istatistikleri kullanarak state answer özelliğini güncelliyoruz.
  3. Ayrıca, componentDidMount() yönteminde, axios kitaplığını kullanarak bir POST/Answers HTTP isteği yaparak sunucudan mevcut cevap istatistiklerini almak için, Pusher ile bağlantı kuruyoruz. Sunucudan aldığımız güncellenmiş istatistikleri kullanarak state answers özelliğini güncelliyoruz.

Şimdi, az önce oluşturduğumuz Poll ve Stats bileşenlerini içe aktaracağız ve bunları işlenmiş DOM'a ekleyeceğiz.

pages/index.js dosyamızda şu değişiklikleri yapmakla, işe başlayabiliriz.

    /* pages/index.js */

    import axios from 'axios';
    import Pusher from 'pusher-js';
    import Poll from '../components/Poll';
    import Stats from '../components/Stats';

Ardından, yeni bileşenleri render() yöntemindeki <section> öğelerine ekleyin.

    /* pages/index.js */

    render() {
      const question = `What is the Most Populated Country in the World?`;
      const choices = ['China', 'Brazil', 'Indonesia', 'India', 'U.S.'];

      return (
        <Layout pageTitle="Realtime Data Visualization">
          <main className="container-fluid position-absolute h-100 bg-light">
            <div className="row position-absolute w-100 h-100">

              <section className="col-md-7 d-flex flex-row flex-wrap align-items-center align-content-center px-5 border-right border-gray">
                <div className="px-5 mx-5">
                  <Poll question={question} choices={choices} />
                </div>
              </section>

              <section className="col-md-5 position-relative d-flex flex-wrap h-100 align-items-start align-content-between bg-white px-0">
                <Stats choices={choices} stats={this.state.answers} />
              </section>

            </div>
          </main>
        </Layout>
      );
    }

Buraya bir soru ve ilgili seçenekleri ekledik ve bunları prop olarak Pollbileşenine ilettik.

Artık dizin sayfamız tamamlandı ve bir parça dışında her şey mükemmel çalışıyor. Uygulamayı tarayıcınızda npm run dev ile test ederseniz, verilen cevapların grafikte bir değişikliği yaratmadığını fark edebilirsiniz.

Sorunun Çözümü

Sizin de gözlemlemiş olabileceğiniz gibi, cevabınızı göndermeye çalışmak veri görselleştirmesini değiştirmedi. Bunun nedeni, sunucuda henüz /answer ve /answers yollarını uygulamamış olmamızdır. Hadi bu kısmı da halledelim.

server.js dosyasını değiştirin ve then() işlevi içindeki server.listen() çağrısından hemen önce aşağıdakileri ekleyin.

    /* server.js */

    // server.get('*')......

    let answers = {};

    server.post('/answer', (req, res, next) => {
      const { choice = null } = req.body;

      if (choice) {
        const hasChoice = choice in answers && typeof answers[choice] === 'number';
        const count = ( hasChoice ? Math.max(0, answers[choice]) : 0 ) + 1;

        answers = { ...answers, [choice]: count };

        pusher.trigger('poll-board', 'new-answer', { choice, count });
      }
    });

    server.post('/answers', (req, res, next) => {
      res.json({ answers, status: 'success' });
    });

    // server.listen().....

İlk olarak, yanıt sayılarını takip etmek ve yanıt istatistiklerimiz için bir tür bellek içi depo oluşturduk. Bu, güncel istatistikleri görmek ve kanala katılan yeni müşteriler için kullanışlıdır. Pusher istemcisi bağlantı sırasında /answers uç noktasına bir POST isteği yaptığında, döndürülen yanıttaki tüm güncel yanıt istatistiklerini alır.

POST/answer rotasında, daha önce eklediğimiz body-parser middleware'in yardımıyla req.body'den seçilen seçeneği alıyoruz. Ardından, answersnesnesinden seçilen seçimin sayısını alıyoruz ve 1 artırıyoruz.

Son olarak, yanıt istatistiklerini artışı yansıtacak şekilde güncelliyoruz ve ardından poll-board Pusher kanalında güncellenmiş yanıt istatistiklerini geçerek yeni bir yanıt etkinliğini tetikliyoruz.

Buraya kadar sorunsuz bir şekilde geldiyseniz sizleri kutluyorum. Next.js ve Pusher'ı kullanarak gerçek zamanlı bir veri görselleştirme uygulamasını başarıyla oluşturdunuz.

Her şeyin çalıştığını görmek için uygulamayı şimdi tarayıcınızda test edin. Ayrıca yaptığınız grafikleri ve oluşturduğunuz anketleri instagram ve linkedIn üzerinden benimle paylaşabilirsiniz. Sorularınız olursa, lütfen sormaktan çekinmeyin.

Özet

Bu makalede, Next.js, React , Chart.js ve Pusher kullanarak çok basit bir gerçek zamanlı veri görselleştirme uygulaması oluşturduk.

Bu makaleyi olabildiğince basit tutmaya çalıştım. Sadece anket sayılarıyla ilgilendik. Gerçek bir uygulamada, zamana dayalı görselleştirme, anket oranı görselleştirme ve gerçek zamanlı sonuçların istatistiksel analizi gibi şeyler yapmak isteyebilirsiniz.

Bunları kullanmanın diğer yolları hakkında daha fazla bilgi edinmek için bu projede kullandığımız her teknolojinin belgelerini muhakkak incelemenizi tavsiye ederim. Umarım bu makale size yardımcı olur.

Kendinize çok iyi bakın.

Mutlu Kodlamalar...