7 Mayıs 2020 Perşembe

React Native (11) - Hooks yapısı ve forwardRef, useImperativeHandle, useRef ile bir componentin bileşenlerine erişme

Marhaba,
bu yazımda React hooks  ile birlikte gelen forwardRef, useImperativeHandle, useRef  fonksiyonlarını inceleyeceğiz. 

React native ile uygulama geliştirirken bazen tüm ekranı render etmeden bir componetten başka bir componentin state'ini değitirerek sadce erişilen component'i render etmek isteyebilirsiniz. Bu gibi durumlarda referans kullanımı size yardımcı  olabilir.

Bu yazı için geliştirilen örnek uygulama da ToastMessageHooks adında  bir main component oluşturulur. Daha sonra CustomToastMessage adlı bir component oluşturularak girilen mesajı ekrana yazdıracak şekilde içeriği güncellenir.

ToastMessageHooks componenti içinde bir TextInput alanı ve buradan girelecek mesajı CustomToastMessage componentine gönderecek bir Button eklenir.
Toast mesajlarının erkana bastıracak CustomToastMessage componenti de yine  ana component(ToastMessageHooks) içinde çağrılır.

Durumu daha iyi kavrayabilmek için aşağıdaki adımları inceleyebilirsiniz. Yine github üzerinden CustomToastMessage ve CustomToastMessage componentlerini inceleyebilirsiniz.

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

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

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

export const CustomToastMessage = forwardRef((props, ref) => {
  const [message, setMessage] = useState();
  const [isVisible, setIsVisible] = useState();

  const showToast = msg => {
    setIsVisible(true);
    setMessage(msg);
  };

  const hideToast = () => {
    setIsVisible(false);
    setMessage(null);
  };

  useImperativeHandle(ref, () => {
    return {
      show: showToast,
      hide: hideToast,
    };
  });

  if (!isVisible) {
    return null;
  }
  return (
    <View style={styles.toast}>
      <Text>{message}</Text>
    </View>
  );
});


ToastMessageHooks adında bir component oluşturn. İçeriği aşağıdaki gibi olmalıdır.

export const ToastMessageHooks = props => {
  const [desc, setDesc] = useState();

  const toastRef = useRef(null);

  const showToastMessage = d => {
    toastRef.current.show(d);
  };

  const hideToastMessage = () => {
    toastRef.current.hide();
  };

  return (
    <View style={styles.container}>
      <TextInput style={styles.input} onChangeText={d => setDesc(d)} />
      <AppButton        style={{marginTop: 10}}
        title="Show toast message"        onBtnPress={() => showToastMessage(`Message is ${desc}`)}
      />
      <AppButton        style={{marginTop: 10}}
        title="Hide toast message"        onBtnPress={() => hideToastMessage()}
      />
      <CustomToastMessage ref={toastRef} />
    </View>
  );
};


Son olarak her iki componentit de kapsayan tüm tanımlamaları kök dizindeki App.js dosyasına aşağıdaki gibi ekleyebilirsiniz.

import React, {
  Component,
  forwardRef,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';
import {StyleSheet, Text, TextInput, View} from 'react-native';
import {AppButton} from 'appComponent/Button';

export default class App extends Component {
  render() {
    return (
      <>
        <ToastMessageHooks />
      </>
    );
  }
}

export const CustomToastMessage = forwardRef((props, ref) => {
  const [message, setMessage] = useState();
  const [isVisible, setIsVisible] = useState();

  const showToast = msg => {
    setIsVisible(true);
    setMessage(msg);
  };

  const hideToast = () => {
    setIsVisible(false);
    setMessage(null);
  };

  useImperativeHandle(ref, () => {
    return {
      show: showToast,
      hide: hideToast,
    };
  });

  if (!isVisible) {
    return null;
  }
  return (
    <View style={styles.toast}>
      <Text>{message}</Text>
    </View>
  );
});

export const ToastMessageHooks = props => {
  const [desc, setDesc] = useState();

  const toastRef = useRef(null);

  const showToastMessage = d => {
    toastRef.current.show(d);
  };

  const hideToastMessage = () => {
    toastRef.current.hide();
  };

  return (
    <View style={styles.container}>
      <TextInput style={styles.input} onChangeText={d => setDesc(d)} />
      <AppButton        style={{marginTop: 10}}
        title="Show toast message"        onBtnPress={() => showToastMessage(`Message is ${desc}`)}
      />
      <AppButton        style={{marginTop: 10}}
        title="Hide toast message"        onBtnPress={() => hideToastMessage()}
      />
      <CustomToastMessage ref={toastRef} />
    </View>
  );
};

const styles = StyleSheet.create({
  toast: {
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 0,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'green',
    zIndex: 11,
    height: 60,
  },
  container: {
    flex: 1,
    paddingTop: 50,
    margin: 10,
  },
  input: {height: 40, borderWidth: 1, marginBottom: 10},
  paragraph1: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: 'blue',
  },
  paragraph2: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});


birkaç önemli nokta:
  • Hooks ile birlikte referans kullanabilmek için useRef import edilmelidir. ÖRN: import {useRef} from 'react';
  • useRef tanımı uygulamada aşağıdaki gibi tanımlanmıştır

    const toastRef = useRef(null);



    <CustomToastMessage ref={toastRef} />

  • Varsayılan durumda reactın compomentlerine useRef ile referans verilebilir.
  •  uygulamada CustomToastMessage componentinin hide() ve show(message) methodlarına aşağıdaki gibi erişilmiştir.

    const toastRef = useRef(null);
    
    const showToastMessage = d => {
      toastRef.current.show(d);
    };
    
    const hideToastMessage = () => {
      toastRef.current.hide();
    };

  • Ancak kendi yazdığınız bir compoment'e referans vermek isterseniz yazdığınız bo component'i forwardRef methodundan türetmeniz gerekmektedir.
  • forwardRef methodunu kullanmak için react'tan import etmek gerekir. ÖRN: import {forwardRef} from 'react';
  • forwardRef ile  CustomToastMessage componenti aşağıdaki gibi oluşturulmuştur.

    export const CustomToastMessage = forwardRef((props, ref) => {...}

  • Ayrıca forwardRef ile oluşturduğunuz referans'ın component dışından hangi bileşenlerine erişebileceğini de useImperativeHandle methoduyla belirtilmektedi.
  • Yine useImperativeHandle methodunu React'tan import edilerek dosyada çağrılabilir. ÖRN: import {useImperativeHandle} from 'react';
  • showToast ve hideToast methodlarını referanslı erişime açmak için aşağıdaki şekilde tanım yapılmıştır.

    useImperativeHandle(ref, () => {
      return {
        show: showToast,
        hide: hideToast,
      };
    });






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

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

Hiç yorum yok:

Yorum Gönderme