5 Mayıs 2020 Salı

React Native (10) - Hooks yapısı ve React.memo ile bir component'i cachelemek

Marhaba,
bu yazımda React ile birlikte gelen memo fonksiyonunu inceleyeceğiz. 
Bu fonksiyona parametre olarak verilen component,  ekran render olduğunda bir kez çalışmaktadır.
Daha sonra  component'in state ve props'unda bir değişiklik olmadığı sürece cache den değer dönülmektedir. Dolayısıyla gereksiz reRender işleminden kaçmak için bu yöntem kullanılabilir.

Geliştirilen örnek çalışmada, içinde başlangıç tarihi(yıl/ay)  ve bitiş tarihi(yıl/ay) olan bir ekran tasarlanmıştır. Ay ve Yıl bilgilerini başlıklarıyla birlikte ekrana basan "YearMonthViewer" adında bir component oluşturulmuştur. Yine aynı ekrana ay ve yıllara random değerler atayabilmek için  4 adet buton eklenmiştir.

Varsayılan durumda butonlara he basma işleminde state değişikliği olacağı için  ekranın tamamı  reRender olmaktadır.

Ancak YearMonthViewer componenti  export default React.memo(YearMonthViewer); şeklinde tanımlandığı için ana ekranda bu component'in kaç kez çağrıldığına bakılmaksızın  sadece değişikliğin bağlı olduğu component(YearMonthViewer) reRender edilmektedir.

Bu fonksiyonun kullanımmı oldukça basit olmasına rağmen uygulama performansına katkısı büyüktür.

Durumu daha iyi kavrayabilmek için aşağıdaki adımları inceleyebilirsiniz. Veya tam implementasyonu görmek için git üzerindeki kaynak kodları inceleyebilirsiniz.

ilk olarak react native ile bir proje oluşturun.
$ react-native init someProject

Terminal üzerinden projenin bulunduğu dizine gidin.
$ cd someProject

YearMonthViewer adında bir component oluşturun ve dosya içeriğini aşağıdaki şekilde güncelleyin.

import React from 'react';
import {StyleSheet, Text} from 'react-native';

const styles = StyleSheet.create({
  paragraph2: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: 'red',
  },
});

function YearMonthViewer({title, year}) {
  console.warn(`YearMonthViewer - title : ${title} - year : ${year}`);
  return (
    <Text style={styles.paragraph2}>
      {title} : {year}
    </Text>
  );
}

export default React.memo(YearMonthViewer);


cacheleme yapan kısım  : export default React.memo(YearMonthViewer);
React.memo kısmını kaldırarak test ederseniz her butona bastığınızda YearMonthViewer componenti ana ekranda çağrıldığı kadar(4 kez) render edilecektir.  Mevcut durumda ise her butona basıldığında YearMonthViewer componenti sadece 1 kez render edilmektedir.

NOT: ReRender işlemlerinin gözle farkedilebilmesi için YearMonthViewer componentine warn seviesinde log eklenmiştir.

Üstte tanımlanan component'ide kapsayan bir ekran oluşturmak için  DateRangeHooks adında bir component oluşturun.
İçinde tarih aralıkları ve güncelleme butonları bulunan Component aşağıdaki gibi tanımlanmalıdır.

import React, {useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {AppButton} from 'appComponent/Button';
import YearMonthViewer from 'appComponent/YearMonthViewer';
import {random} from 'appUtil';

export const DateRangeHooks = props => {
  const [startYear, setStartYear] = useState(2020);
  const [endYear, setEndYear] = useState(2050);
  const [startMonth, setStartMonth] = useState(1);
  const [endMonth, setEndMonth] = useState(5);

  return (
    <View style={styles.container}>
      <View style={styles.grouping}>
        <YearMonthViewer title="Start Year" year={startYear} />
        <YearMonthViewer title="End Year" year={endYear} />
      </View>

      <View style={styles.grouping}>
        <YearMonthViewer title="Start Month" year={startMonth} />
        <YearMonthViewer title="End Month" year={endMonth} />
      </View>

      <View style={styles.grouping}>
        <AppButton          style={styles.startDateBtn}
          title="change start Year"          onBtnPress={() => setStartYear(random(2000, 2020))}
        />

        <AppButton          style={{marginTop: 5}}
          title="change end Year"          onBtnPress={() => setEndYear(random(2020, 2050))}
        />
      </View>

      <View style={styles.grouping}>
        <AppButton          style={styles.startDateBtn}
          title="change start month"          onBtnPress={() => setStartMonth(random(1, 12))}
        />

        <AppButton          style={{marginTop: 5}}
          title="change end month"          onBtnPress={() => setEndMonth(random(1, 12))}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    margin: 10,
  },
  input: {height: 40, borderWidth: 1, marginBottom: 10},
  paragraph1: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: 'blue',
  },
  grouping: {
    flex: 1,
    maxHeight: 100,
    flexDirection: 'row',
  },
  startDateBtn: {marginTop: 5, backgroundColor: 'skyblue'},
});


index.js dosyasında render methodunda aşağıdaki şekilde tasarladığınız ekranı aşağıdaki şekilde çağırarak test edebilirsiniz.

render() {
  return <DateRangeHooks/>;
}


github(state) : https://github.com/lvntyldz/tutorials/tree/9-react-hooks-usememo/react-native-hooks-examples

github(projenin tamamı) : https://github.com/lvntyldz/tutorials/tree/master/react-native-hooks-examples

Hiç yorum yok:

Yorum Gönder