React Native ile Mobil Uygulama Geliştirme – 18 – Detaylı Flexbox Kullanımı

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 18. kısmıdır. Bir önceki makalede (Part 17). React Native’de Asyncstorage ile React Native’de Redux Persist ile uygulamalarda sayfa değiştiğinde, yenilendiğinde veya uygulama kapatıp tekrar açıldığında, tekrar eski haline dönmesini veya sıfırlanmasını engellemeyi anlattım.

React Native uygulamamızın sayfalarında yer alan bölümlerin yapılandırılmasının çalışmalarını Flexbox yapısı ile detaylı öğreneceğiz. Flex yapısı react-native ortamında style işleri ile uğraşan biri için öğrenilmesi gereken en önemli konulardan biridir. Hayatımıza girmesi ile beraber esnek yapı kurmak istediğimizde bizim işimizi kolaylaştırmıştır.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Başlarken
Basit bir örnekle başlayalım. Üç Metin bileşenine sahip bir View komponent içeren konteynir ekleyelim.

//Our views
<View style={styles.container}>
  <View style={styles.viewStyleOne}>
    <Text style={styles.textStyle}> 1 </Text>
  </View>
  <View style={styles.viewStyleTwo}>
    <Text style={styles.textStyle}> 2 </Text>
  </View>
  <View style={styles.viewStyleThree}>
    <Text style={styles.textStyle}> 3 </Text>
  </View>
</View>
//Styles
let styles = StyleSheet.create({
  container: { backgroundColor:'#4286f4'},
  viewStyleOne: {
    width:40,
    height:40,
    justifyContent: 'center',
    alignItems:'center', 
    backgroundColor:'#b642f4'
  },
  textStyle:{
    textAlign:'center'
  }
})

Ekran Görüntüsü:

Konteynerin Şekillendirilmesi
Şimdi konteynere flex:1 ekliyoruz:

container: { 
  backgroundColor:'#4286f4', 
  flex: 1 
}

Bu, konteynerin ebeveynini, yani tüm ekranı doldurmasını sağlar.

Şimdi ekliyoruz:

container: { 
  backgroundColor:'#4286f4', 
  flex: 1,
  flexDirection:'row'
}

Herbir flexDirection view’leri, varsayılan olarak sütuna ayarlıdır, ancak bunu ‘satır’ olarak ayarlamak, konteynerdeki öğelerin yönünü değiştirecektir.

Artık içeriğin yönünü flexDirection kullanarak kontrol edebiliriz.
Şimdi justifyContent ve alignItems ekleyelim:

container:{ 
  backgroundColor:'#4286f4', 
  flex: 1, 
  flexDirection: 'row',
  justifyContent: 'flex-end',
  alignItems:'flex-start'
}

Benzer şekilde:

container: { 
  backgroundColor:'#4286f4', 
  flex: 1, 
  flexDirection: 'row',
  justifyContent: 'flex-end',
  alignItems:'flex-end'
}

Görünümler aşağıdaki gibi işlenecektir:

flexDirection, birincil ekseni ‘satır’ veya ‘sütun’ olarak belirler.
justifyContent, child’ların birincil eksen boyunca dağılımını belirler.
alignItems, child’ların ikincil eksen boyunca hizalamasını belirler.
Öğeleri ortalanacak şekilde ayarlamak için:

justifyContent: 'center',
alignItems:'center'

justifyContent flex-startcenterflex-endspace-around ve space-between destekler.
space-around:

space-between:

alignItemsflex-startcenterflex-end,ve stretch destekler.

Konteyner Stilini Geçersiz Kılma
Geçersiz kılmak için bir öğeye ihtiyacımız varsa, konteyner tarafından tanımlandığı gibi tanımlanır, öğeleri ayrı ayrı stil kullanabiliriz.
alignSelf, alignItems öğelerini geçersiz kılar ve bu seçenekleri autoflex-startflex-endcenterstretch and baseline olarak destekler.
Bir öğeye kendisini flex-start hizalamasını söylersek,

alignSelf: 'flex-start'

Böyle bitecekti:

flexGrow, öğenin aynı konteyner içindeki diğer esnek öğelere göre ne kadar büyüyeceğini kontrol eder.

flexGrow: 1

Şu şekilde işlenir:

flexBasic, öğe boyutunu yüzde ile kontrol eder. Örneğin:

flexBasis:50 //firstView style
flexBasis:20 //secondView style
flexBasis:30 //ThirdView style

Ve bu kadar! Umarım bu makaleyi faydalı bulmuşsunuzdur.

Kaynak: https://blog.reactnativecoach.com/

 

React Native ile Mobil Uygulama Geliştirme – 17 – Asyncstorage ile React Native’de Redux Persist Nasıl Kullanılır?

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 17. kısmıdır. Bir önceki makalede (Part 16),React Native ile geliştirilen mobil uygulamanızda, fetch API ile kullanıcılarınıza resim yükleme işlemini nasıl yapabileceğiniz anlattım.
Bu makalede Asyncstorage ile React Native’de Redux Persist ile uygulamalarda sayfa değiştiğinde, yenilendiğinde veya uygulama kapatıp tekrar açıldığında, tekrar eski haline dönmesini veya sıfırlanmasını engellemeyi öğreneceğiz.
Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Redux kullandığımız uygulamalarda, sayfa değiştiğinde, yenilendiğinde veya uygulama kapatıp tekrar açıldığında, redux’ taki değişkenlerin tekrar eski haline dönmesi veya sıfırlanması sebebiyle tekrar kullanmak istediğimizde ulaşamayız. Bu yüzden sayfa yenilendiğinde tekrar istek atar ve değişkenleri tekrar setleriz. Özellikle genelde servisten gelen sabit objeler veya arraylerde bu can sıkıcı hale gelir çünkü tekrar servise istek atıp değişkeni tekrar setlemek gerekir.

Redux persist, redux’taki değişkenlerin, sayfa yenilendiğinde, değiştiğinde veya uygulama kapatıp tekrar açıldığında tekrar eski haline dönmesini veya sıfırlanmasını engellemeye yarayan, bu değişkenleri localstorage da saklayan bir pakettir.

Redux Persist, bir uygulamanın yerel deposunda bir Redux store kaydedilmesine izin veren bir kitaplıktır. React Native terimleriyle, Asyncstorage, global olan ve uygulama için yerel depolama olarak kullanılabilen, anahtar/değer tabanlı, şifrelenmemiş, eşzamansız bir depolama sistemidir.

Bir React Native uygulamasında Redux gibi bir durum yönetimi kitaplığı kullanmak, bir uygulamanın durumunu tek bir yerden yönetmek için faydalıdır. Uygulamanız özellikler açısından ilerledikçe, her kullanıcı için yerel olan bazı bilgileri kalıcı kılmak isteyebilirsiniz.

Örneğin, bir alışveriş sepeti uygulaması oluşturuyorsunuz ve bir satın alma siparişi vermeden önce kullanıcının sepete eklediği ürünlerle ilgili verilerin kalıcı olmasını gerektiriyor. Kullanıcı, bu satın alma işlemini yapmadan önce uygulamayı keyfi bir nedenle kapatırsa ancak daha sonra geri dönerse ve bu sayıda öğenin sepetinden tamamen silineceğini görürse ne olur? Bu iyi bir kullanıcı deneyimi değil.

Bu kullanıcı deneyimini geliştirmek için öğeleri, cihazlarının yerel deposuna kaydedebilirsiniz. Asyncstorage ile birlikte redux-persist’in bir React Native uygulaması için kullanışlı olduğu yer burasıdır. Bu makalede, durum yönetimi kitaplığı olarak Redux kullanan bir React Native uygulamasında redux-persist kitaplığını kuracağız ve uygulamanın kapalı olduğu senaryolar için verileri Asyncstorage’da koruyacağız.

Gereksinimler
Bu makaleyi takip etmek için lütfen JavaScript/ES6’ya aşina olduğunuzdan ve yerel geliştirme ortamınızda aşağıdaki gereksinimleri karşıladığınızdan emin olun:

Node.js sürümü >= 12.x.x kurulu.
npm veya thread veya npx gibi bir paket yöneticisine erişim sağlayın.
Redux store, actions, and reducers, expo-cli, ve use npx hakkında temel bir anlayışa sahip olun.

expo-cli ile bir React Native uygulaması oluşturun
expo-cli kullanarak yeni bir React Native projesi oluşturun ve ardından bu demo uygulamasını oluşturmak için gereken bağımlılıkları yükleyin. Bir terminal penceresi açın ve aşağıdaki komutları yürütün:

npx expo init redux-persist-asyncstorage-example # navigate into that directory cd redux-persist-asyncstorage-example yarn add @react-navigation/native @react-navigation/bottom-tabs axios@0.21.0 redux@4.0.5 redux-persist@6.0.0 redux-thunk@2.3.0 react-redux@7.2.2 # install dependencies with Expo specific package version expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view @react-native-async-storage/async-storage

Bu bağımlılıkları yükledikten sonra demo uygulaması için çekirdek ekranlar olacak iki adet sahte ekran oluşturalım. Yeni bir screens/dizin oluşturun ve bunun içinde aşağıdaki kod parçacığıyla BooksList.js ilk ekran dosyasını oluşturun:

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

export default function BooksListApp() {
  return (
    
      BooksList
    
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  }
});

Ardından, aşağıdaki kod parçacığıyla BookmarksList.js ikinci ekran dosyasını oluşturun:

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

export default function BookmarksList() {
  return (
    
      BookmarksList
    
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  }
});

BooksList ekranı kitapların bir listesini gösterecek. Kitapları görüntülemek için verileri getireceğim ve temel URL olarak Draftbit‘in Örnek API yolunu kullanacağım.

Bu ekranda gösterilen her kitap öğesi, son kullanıcının daha sonra görüntülemek üzere gerçek zamanlı olarak işaretlemesi veya kaydetmesi için bir işlevselliğe sahip olacaktır. Kullanıcı tarafından kaydedilen tüm kitap öğeleri BookmarksList sekmesinde gösterilecektir.

Verileri getirmek için bir Temel URL gerektiğinden, onu ekleyelim. config/ adlı yeni bir dizin oluşturun ve bunun içinde index.js adlı bir dosya oluşturun ve aşağıdaki Temel URL’yi dışa aktarın:

export const BASE_URL = 'https://example-data.draftbit.com/books?_limit=10';

Artık bu Temel URL, HTTP istekleri göndermek için kullanıma hazırdır.

Ekranlar arasında geçiş yapmak için stab navigation ekleyin
Bu bölümde, uygulamanın bir önceki bölümde oluşturulan iki sahte ekranı göstermesi için altta özel bir sekme gezgini oluşturalım. Bir navigation/ dizin oluşturarak ve RootNavigator.js adlı yeni bir dosyanın içinde başlayın. Bu dosyaya aşağıdaki içe aktarma ifadelerini ekleyin:

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';

// Import mock screens
import BooksList from '../screens/BooksList';
import BookmarksList from '../screens/BookmarksList';

const Tab = createBottomTabNavigator();

Sekme çubuğu görünümünü özelleştirmek için, expo paketiyle önceden yüklenmiş olarak gelen @expo/vector-icons kitaplığından bazı stil ve özel simgeler ekleyelim.

const tabBarOptions = {
  showLabel: false,
  inactiveTintColor: '#2D3038',
  activeTintColor: '#FFFFFF',
  style: {
    height: '10%',
    backgroundColor: '#1E1B26'
  }
};

const screenOptions = (route, color) => {
  let iconName;

  switch (route.name) {
    case 'BooksList':
      iconName = 'view-dashboard';
      break;
    case 'BookmarksList':
      iconName = 'bookmark-multiple-outline';
      break;
    default:
      break;
  }

  return <MaterialCommunityIcons name={iconName} color={color} size={24} />;
};

tabBarOptions yapılandırma nesnesi, farklı uygulama ekranları arasında paylaşılan alt sekmenin görünümünü özelleştirecek. ScreenOptions, her sekme için özel bir simge eklemek için kullanılır.

Son olarak bu iki sekme ekranını oluşturacak RootNavigator bileşenini tanımlayıp dışa aktaralım.

const RootNavigator = () => {
  return (
    <NavigationContainer>
      <Tab.Navigator
        initialRouteName='BooksList'
        tabBarOptions={tabBarOptions}
        screenOptions={({ route }) => ({
          tabBarIcon: ({ color }) => screenOptions(route, color)
        })}
      >
        <Tab.Screen name='BooksList' component={BooksList} />
        <Tab.Screen name='BookmarksList' component={BookmarksList} />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

export default RootNavigator;

RootNavigator’ı çalışırken görmek için, onu App.js dosyasının içine alın ve geri gönderin. App.js dosyasına aşağıdaki kod parçacığını ekleyin:

import React from 'react';

import RootNavigator from './navigation/RootNavigator';

export default function App() {
  return <RootNavigator />;
}

Uygulamayı çalıştırmak için terminal penceresinden yarn start komutunu çalıştırın.

İşte bu adımdan sonraki çıktı

Action Types ve creators ekleyin
Tüm uygulamanın durumunu yönetmek için Redux kullanıldığında, durumun kendisi bir JavaScript nesnesi tarafından temsil edilir. Bu nesne salt okunurdur, yani durum manipülasyonu doğrudan yapılmaz. Değişiklikler, eylemleri tetikleyerek yapılır.

Action Types tanımlayarak başlayalım. redux/ adında yeni bir dizin oluşturun ve bunun içinde action.js adında yeni bir dosya oluşturun. Aşağıdaki action types buna ekleyin:

// Define action types
export const GET_BOOKS = 'GET_BOOKS';
export const ADD_TO_BOOKMARK_LIST = 'ADD_TO_BOOKMARK_LIST';
export const REMOVE_FROM_BOOKMARK_LIST = 'REMOVE_FROM_BOOKMARK_LIST';

Yukarıdaki dosyada tanımlanan eylem türleri açıklayıcıdır. İlki, GET_BOOKS, Temel URL’den veri almak için HTTP isteğinde bulunmak için kullanılacaktır. İkincisi, ADD_TO_BOOKMARK_LIST, her kitap öğesini yer imleri listesine ekleyecektir. Benzer şekilde, üçüncü eylem türü REMOVE_FROM_BOOKMARK_LIST, kitabı yer imleri listesinden çıkaracaktır.

Redux kullanılarak depolanan durumu güncellemek için olayı tetiklemek için bir eylem türü kullanılır. Her eylem türünün bu amaç için eylem oluşturucuları vardır. Demo uygulamasında gereken ilk eylem oluşturucu, verileri Draftbit’in Örnek API’sinden getirmektir.

Verileri almak için axios adlı bir kütüphane kullanacağız. Uygun HTTP isteklerini yapmak için .get, .put vb. yöntemlerden oluşan bir API’ye sahiptir.

Verileri almak üzere HTTP isteğinde bulunmak için API’nin bir BASE URL’si gereklidir. Action.js dosyasının içinde, axios kitaplığını ve Temel URL’yi içe aktarın:

import axios from 'axios';

import { BASE_URL } from '../config';

 

Eylem türlerini tanımladıktan sonra, aşağıdaki kod parçacığıyla GET_BOOKS eylem türüne sahip getBooks adlı yeni bir eylem oluşturucu tanımlayın:

export const getBooks = () => {
  try {
    return async dispatch => {
      const response = await axios.get(`${BASE_URL}`);
      if (response.data) {
        dispatch({
          type: GET_BOOKS,
          payload: response.data
        });
      } else {
        console.log('Unable to fetch data from the API BASE URL!');
      }
    };
  } catch (error) {
    // Add custom logic to handle errors
    console.log(error);
  }
};

Reducer ekleme
Bir eylem tetiklendiğinde, uygulamanın durumu değişir. Uygulamanın durumunun işlenmesi bir redüktör tarafından yapılır.

Reducer, bir sonraki durumu ilk veya önceki duruma göre hesaplayan saf bir işlevdir. Durum değişmezse her zaman aynı çıktıyı üretir. State ve action olmak üzere iki girdi alır ve varsayılan state’i döndürmesi gerekir.

redux/ dizininde reducers.js adlı yeni bir dosya oluşturun. GET_BOOKS action türünü içe aktarın ve ardından ilk durumu iki boş diziyle tanımlayın. Ardından, ilk bağımsız değişken için varsayılan değer olarak initialState’i ve ikinci bağımsız değişken olarak eylemi alan bir bookReducer işlevi tanımlayın.

import { GET_BOOKS } from './actions';

const initialState = {
  books: [],
  bookmarks: []
};

function booksReducer(state = initialState, action) {
  switch (action.type) {
    case GET_BOOKS:
      return { ...state, books: action.payload };
    default:
      return state;
  }
}

export default booksReducer;

Store yapılandırma
Store, actions ve reducers’ları bir araya getiren bir nesnedir. Tek tek bileşenler yerine uygulama düzeyinde state sağlar ve tutar.

redux/ dizini içinde store.js adında yeni bir dosya oluşturun. Redux’da bir store, rootReducer’ı ilk argüman olarak ve bir ara katman yazılımı veya ikinci argüman olarak bir ara katman yazılımı işlevleri koleksiyonunu alan createStore adlı bir işlev kullanılarak oluşturulur.

rootReducer, uygulama genelinde farklı reducer’ların bir kombinasyonudur. Demo uygulamasında sadece bookReducer adında bir reducer bulunmaktadır.

Ara yazılım işlevi thunk, bir redux store’nun, bu demo uygulamasında olduğu gibi bir API URL’sinden veri alma gibi asenkron AJAX istekleri yapmasına izin verir.

Buna aşağıdaki kod parçasını ekleyin:

import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import booksReducer from './reducers';

const rootReducer = combineReducers({ booksReducer });

export const store = createStore(rootReducer, applyMiddleware(thunk));

Bu Redux store’nu React Native uygulamasında bağlamak için App.js giriş noktası dosyasını açın. İçine, store’u ve High Order Component Provider'i react-redux paketinden içe aktarın. Bu HOC, store’u, artık state’e erişebilen tüm bileşenler gibi uygulamanın geri kalanına aktarmaya yardımcı olur. Ayrıca, tüm ekranlar bu custom navigator’ın çocukları olduğundan, RootNavigator’ı da saracaktır.

App.js dosyasını aşağıda gösterildiği gibi değiştirin:

import React from 'react';
import { Provider } from 'react-redux';

import { store } from './redux/store';
import RootNavigator from './navigation/RootNavigator';

export default function App() {
  return (
    <Provider store={store}>
      <RootNavigator />
    </Provider>
  );
}

API’den veri alma
BooksList.js dosyası, verilerin Temel URL’den getirileceği sekmedir. Aşağıdaki ifadeleri içe aktarın.

import React, { useEffect } from 'react';
import {
  Text,
  View,
  FlatList,
  TouchableOpacity,
  Image,
  SafeAreaView
} from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import { MaterialCommunityIcons } from '@expo/vector-icons';

import { getBooks } from '../redux/actions';

Bir Redux store’dan state’e erişmek için useSelector kancası kullanılır. BooksList bileşeninin içinde, kitaplara erişin.

export default function BooksList() {
  const { books } = useSelector(state => state.booksReducer);

  //...
}

Redux store’dan bir action göndermek için useDispatch kancası kullanılır. Kitapları API’den getirmek için getBooks eylemini göndermeniz gerekir. State’e eriştikten sonra aşağıdaki kod parçasını ekleyin.

const dispatch = useDispatch();

const fetchBooks = () => dispatch(getBooks());

useEffect(() => {
  fetchBooks();
}, []);

Ardından, kitap listesini oluşturmak için bir FlatList bileşeniyle dönüş JSX’i ekleyin.

API’den getirilen kitaplar bir dizidir ve verilerin değeri olarak iletilir.

return (
  
    
      Bestsellers
      
         item.id.toString()}
          renderItem={renderItem}
          showsVerticalScrollIndicator={false}
        />
      
    
  
);

renderItem’den döndürülen JSX, listedeki her kitap öğesi için görüntülenecek tüm bilgileri içerir.

Her kitap öğesi şunlara sahip olacak:

Görüntü bileşeni kullanılarak görüntülenen bir kitap kapağı.
Metin bileşeni kullanılarak görüntülenen bir kitap başlığı.
sayfa sayısı ve kitap öğesinin ortalama derecelendirmesi gibi bazı meta bilgiler.
Kitabı BookmarksList ekranına eklemek için dokunulabilir düğme.
Ana dönüş işlevinden hemen önce aşağıdaki renderItem’i ekleyin.

const renderItem = ({ item }) => {
  return (
    
      
        {/* Book Cover */}
        
        {/* Book Metadata */}
        
          {/* Book Title */}
          
            
              {item.title}
            
          
          {/* Meta info */}
          
            
            
              {item.num_pages}
            
            
            
              {item.rating}
            
          
          {/* Buttons */}
          
             console.log('Bookmarked!')}
              activeOpacity={0.7}
              style={{
                flexDirection: 'row',
                padding: 2,
                backgroundColor: '#2D3038',
                borderRadius: 20,
                alignItems: 'center',
                justifyContent: 'center',
                height: 40,
                width: 40
              }}
            >
              
            
          
        
      
    
  );
};

İşte bu adımdan sonra alacağınız çıktı:

Action creators ekleyin ve reducer’ı güncelleyin
redux/actions.js dosyasına, bookmarks kullanıcı tarafından eklendiğinde veya kaldırıldığında durumu güncelleyecek iki action creators daha ekleyelim. Her action creator, daha önce tanımladığımız eylem türünü temel alacaktır. Ayrıca, her action creator, bookmark listesine eklenen kitap öğesini kabul edecektir.

export const addBookmark = book => dispatch => {
  dispatch({
    type: ADD_TO_BOOKMARK_LIST,
    payload: book
  });
};

export const removeBookmark = book => dispatch => {
  dispatch({
    type: REMOVE_FROM_BOOKMARK_LIST,
    payload: book
  });
};

Bir sonraki adım, redux store’un state’ini güncellemektir. redux/reducers.js dosyasını açın ve yeni eklediğimiz eylemleri gerçekleştirmek için aşağıdaki kod parçasını değiştirin.

import {
  GET_BOOKS,
  ADD_TO_BOOKMARK_LIST,
  REMOVE_FROM_BOOKMARK_LIST
} from './actions';

const initialState = {
  books: [],
  bookmarks: []
};

function booksReducer(state = initialState, action) {
  switch (action.type) {
    case GET_BOOKS:
      return { ...state, books: action.payload };
    case ADD_TO_BOOKMARK_LIST:
      return { ...state, bookmarks: [...state.bookmarks, action.payload] };
    case REMOVE_FROM_BOOKMARK_LIST:
      return {
        ...state,
        bookmarks: state.bookmarks.filter(book => book.id !== action.payload.id)
      };
    default:
      return state;
  }
}

export default booksReducer;

Redux persist’ı yapılandırın ve entegre edin
Kalıcı bir reducer oluşturmak için aşağıdaki ifadeleri redux/store.js dosyasına aktarın.

import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistStore, persistReducer } from 'redux-persist';

Ardından, aşağıdaki özelliklere sahip bir persistConfig nesnesi ekleyin:

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
  whitelist: ['bookmarks']
};

Yukarıdaki snippet’te, kalıcı bir reducer için yapılandırma oluşturmak için key ve storage gereklidir. Depolama, verileri kaydetmek ve sürdürmek için kullanılan depolama motorunun değerine sahiptir. React Native’de, depolamanın değerini açıkça iletmek esastır. Mevcut demo uygulamasında AsyncStorage’ı kullanalım.

Whitelist bir dizi dize alır. Verileri kaydetmek için başlangıç durumundan hangi nesne anahtarının kullanılacağını tanımlamak için kullanılır. Whitelist sağlanmazsa, redux hem kitaplarda hem de bookmark’da kalır. Bookmark’ı Whitelist’in değeri olarak sağlamak, yalnızca bookmark dizisindeki (şu anda boş olan ancak daha sonra bir bookmark eklendiğinde veya kaldırıldığında doldurulacak) verileri kaydedecektir.

Ardından, rootReducer’ı iki bağımsız değişkenle kalıcı reducer ile güncelleyin: persistConfig ve bookReducer.

Ayrıca, kalıcılığı dışa aktarın. Orijinal store’u saran persistStore tarafından döndürülen bir nesnedir.

const rootReducer = combineReducers({
  booksReducer: persistReducer(persistConfig, booksReducer)
});

export const store = createStore(rootReducer, applyMiddleware(thunk));
export const persistor = persistStore(store);

React Native uygulamalarında, root bileşeni PersistGate ile sarmanız gerekir. Bu bileşen, kalıcı state alınana ve redux’a kaydedilene kadar uygulamanın kullanıcı arabiriminin oluşturulmasını geciktirir.

Redux-persist kitaplığından PersistGate’i içe aktarın ve App.js dosyasındaki redux/store dosyasından kalıcılığı içe aktarın:

// Add
import { PersistGate } from 'redux-persist/integration/react';

// Modify to add persistor
import { store, persistor } from './redux/store';

// Then, modify the JSX returned from App component
// Wrap the root component with PersistGate
return (
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <RootNavigator />
    </PersistGate>
  </Provider>
);

Redux-persist kitaplığını yapılandırmak ve React Native ve Redux uygulamasına entegre etmek budur.

v eklemek veya kaldırmak için işlevsellik oluşturun
Tüm kitap öğeleri, API’den alınan BooksList.js dosyasında gösterilir. Bir kullanıcının bir kitap öğesine yer imi ekleyebileceği veya kaldırabileceği sekme ekranındandır.

Diğer action creators’ı da içe aktararak başlayalım:

// Modify
import { getBooks, addBookmark, removeBookmark } from '../redux/actions';

BookReducer, state’e erişmek için kullanılır. Bookmark dizisine erişmek için değiştirin:

const { books, bookmarks } = useSelector(state => state.booksReducer);

Şimdi useDispatch kancasını kullanarak iki eylemi gönderin ve işleyici işlevlerini oluşturun. Bu işleyici işlevleri, kullanıcı tarafından dokunulabilir bileşene basıldığında tetiklenecektir. Her işleyici işlevi bir argümanı kabul edecek ve bu, FlatList’teki mevcut kitap öğesidir.

const addToBookmarkList = book => dispatch(addBookmark(book));
const removeFromBookmarkList = book => dispatch(removeBookmark(book));

const handleAddBookmark = book => {
  addToBookmarkList(book);
};

const handleRemoveBookmark = book => {
  removeFromBookmarkList(book);
};

Tetiklenen eyleme bağlı olarak uygulamanın kullanıcı arayüzünü dinamik olarak değiştirecek ifExists adlı başka bir işleyici işlevi ekleyelim. Bu işlev, dizide (AsyncStorage’da depolanan) bir kitap öğesinin zaten var olup olmadığına bağlı olarak kullanıcı arabiriminde değişiklikler yapmak için bookmark dizisindeki filtreyi kullanacaktır.

const ifExists = book => {
  if (bookmarks.filter(item => item.id === book.id).length > 0) {
    return true;
  }

  return false;
};

Bookmark listesine bir öğe eklemek veya listeden bir öğe kaldırmak için bir eylem tetiklendiğinde uygulamanın kullanıcı arayüzünü dinamik olarak değiştirmek için TouchableOpacity bileşenini değiştirin.

<TouchableOpacity
  onPress={() =>
    ifExists(item) ? handleRemoveBookmark(item) : handleAddBookmark(item)
  }
  activeOpacity={0.7}
  style={{
    // rest remains same
    backgroundColor: ifExists(item) ? '#F96D41' : '#2D3038'
    //
  }}
>
  <MaterialCommunityIcons
    color={ifExists(item) ? 'white' : '#64676D'}
    size={24}
    name={ifExists(item) ? 'bookmark-outline' : 'bookmark'}
  />
</TouchableOpacity>

Bookmark göster
BookmarksList.js sekmesinde bookmark’a eklenen herhangi bir kitap öğesi gösterilecektir. Bookmark’a eklenmiş öğelerin listesini görüntülemenin yanı sıra, kitap öğelerini listeden çıkarma işlevine de sahip olacak.

Aşağıdaki ifadeleri içe aktararak başlayın. Bu sefer, yalnızca removeBookmark eylem oluşturucuyu içe aktarın.

import React from 'react';
import {
  SafeAreaView,
  Text,
  View,
  FlatList,
  TouchableOpacity,
  Image
} from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import { MaterialCommunityIcons } from '@expo/vector-icons';

import { removeBookmark } from '../redux/actions';

useSelector kancasını kullanmak,bookmark durumuna erişmemizi sağlar. Ardından, useDispatch kancasını kullanmak, bir kitabı bookmark listesinden çıkarmak için eylem oluşturucu ve işleyici işlevini tanımlar.

export default function BookmarksList() {
  const { bookmarks } = useSelector(state => state.booksReducer);
  const dispatch = useDispatch();

  const removeFromBookmarkList = book => dispatch(removeBookmark(book));

  const handleRemoveBookmark = book => {
    removeFromBookmarkList(book);
  };

  //...
}

Son olarak, bu sekme ekranının kullanıcı arayüzü BooksList.js sekmesine benzer olacaktır. FlatList bileşenini kullanarak, işaretlenmiş tüm öğelerin listesini gösterelim.

İşaretlenmiş hiçbir öğe yoksa, bunu iletmek için basit bir mesaj gösterelim. Bu, durumdan bookmark dizisinin uzunluğunu kontrol ederek yapılır.

BookmarksList sekme bileşeni tarafından döndürülen tam JSX:

export default function BookmarksList() {
  // ...
  const renderItem = ({ item }) => {
    return (
      <View style={{ marginVertical: 12 }}>
        <View style={{ flexDirection: 'row', flex: 1 }}>
          {/* Book Cover */}
          <Image
            source={{ uri: item.image_url }}
            resizeMode='cover'
            style={{ width: 100, height: 150, borderRadius: 10 }}
          />
          {/* Book Metadata */}
          <View style={{ flex: 1, marginLeft: 12 }}>
            {/* Book Title */}
            <View>
              <Text style={{ fontSize: 22, paddingRight: 16, color: 'white' }}>
                {item.title}
              </Text>
            </View>
            {/* Meta info */}
            <View
              style={{
                flexDirection: 'row',
                marginTop: 10,
                alignItems: 'center'
              }}
            >
              <MaterialCommunityIcons
                color='#64676D'
                name='book-open-page-variant'
                size={20}
              />
              <Text style={{ fontSize: 14, paddingLeft: 10, color: '#64676D' }}>
                {item.num_pages}
              </Text>
              <MaterialCommunityIcons
                color='#64676D'
                name='star'
                size={20}
                style={{ paddingLeft: 16 }}
              />
              <Text style={{ fontSize: 14, paddingLeft: 10, color: '#64676D' }}>
                {item.rating}
              </Text>
            </View>
            {/* Buttons */}
            <View style={{ marginTop: 14 }}>
              <TouchableOpacity
                onPress={() => handleRemoveBookmark(item)}
                activeOpacity={0.7}
                style={{
                  flexDirection: 'row',
                  padding: 2,
                  backgroundColor: '#2D3038',
                  borderRadius: 20,
                  alignItems: 'center',
                  justifyContent: 'center',
                  height: 40,
                  width: 40
                }}
              >
                <MaterialCommunityIcons
                  color='#64676D'
                  size={24}
                  name='bookmark-remove'
                />
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </View>
    );
  };

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: '#1E1B26' }}>
      <View style={{ flex: 1, paddingHorizontal: 16 }}>
        <Text style={{ color: 'white', fontSize: 22 }}>Bookmarks</Text>
        <View style={{ flex: 1, marginTop: 8 }}>
          {bookmarks.length === 0 ? (
            <Text style={{ color: '#64676D', fontSize: 18 }}>
              Add a book to bookmark list.
            </Text>
          ) : (
            <FlatList
              data={bookmarks}
              keyExtractor={item => item.id.toString()}
              renderItem={renderItem}
              showsVerticalScrollIndicator={false}
            />
          )}
        </View>
      </View>
    </SafeAreaView>
  );
}

Uygulamayı Çalıştırmak
Expo istemcisini çalıştırdığınız simülatöre veya gerçek cihaza gidin ve bir öğeye bookmark ekleyerek veya kaldırarak işlevselliği test edebilirsiniz. Ayrıca, ilk sekmedeki bookmark düğmesinin dinamik kullanıcı arayüzü değişikliklerine dikkat edin.

Expo istemcisini kapattığınızdan emin olun ve ardından Redux store’daki durumun devam edip etmediğini görmek için başlatın.

Ve bu kadar! Umarım bu makaleyi faydalı bulmuşsunuzdur.

Kaynak:https://blog.jscrambler.com/

React Native ile Mobil Uygulama Geliştirme – 16 – React Native ile Görseller Uygulamada Nasıl Yüklenir?

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 16. kısmıdır. Bir önceki makalede (Part 15), React Native Community Blur paketi ile Android ve iOS uygulamalarının arka plan görünümünü bulanık(blur) nasıl yapabileceğimizi anlattım.
Bu makalede React Native uygulamalarına görselleri nasıl yükleyebiliriz konusunu öğreneceğiz.
Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Görseller, bir mobil uygulamaya başka bir boyut katar. Kullanıcı tarafından oluşturulan görüntüler bunu güçlendirir.

Bu makale de React Native ile geliştirilen mobil uygulamanızda, fetch API ile kullanıcılarınıza resim yükleme işlemini nasıl yapabileceğinizi anlatacağım.

Kurulum

Görüntüleri gerçekten yüklemeye başlamadan önce iki proje oluşturacağız:
1-Bir React Native uygulaması
2-Basit Node Server (böylece fotoğrafı yükleyebileceğimiz bir yerimiz var)

React Native App

Burada birkaç şey yapacağız:

1-Her iki uygulamamızın da içinde olacağı bir dizin oluşturma
2-Yeni bir React Native uygulaması oluşturma
3- react-native-image-picker kitaplığını yükleme
4-react-native-image-picker yerel bağımlılıklarını bağlama
Terminalinizde aşağıdakileri çalıştırın:

mkdir image-upload-example
cd image-upload-example
react-native init mobile
cd mobile
npm install --save react-native-image-picker
react-native link react-native-image-picker

Ardından, React Native uygulamanızla ilişkili hem iOS hem de Android uygulamalarında gerekli izinleri etkinleştirmeniz gerekir.

iOS’ta bu, mobile/ios/mobile/Info.plist’te gerçekleşir ve şunu eklemeniz gerekmektedir.

<key>NSPhotoLibraryUsageDescription</key>
<string>For choosing a photo.</string>
<key>NSCameraUsageDescription</key>
<string>For taking a photo.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>For saving a photo.</string>

Android’de, AndroidManifest.xml dosyasını mobil/android’de birkaç dizin aşağısında bulmak ve şunu eklemeniz gerekmektedir.

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Daha sonra, react-native run-ios veya react-native run-android’i çalıştırabilir ve aşağıdakine benzer bir sonuç elde edebilirsiniz:

Node Server

Yeni bir terminal penceresinde aşağıdaki komutları çalıştırın:

cd image-upload-example
mkdir server
cd server
mkdir images
npm init // answer the questions
npm install --save express body-parser multer
touch index.js

Ardından index.js’ye aşağıdakileri yazın:

index.js

const Express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser');

const app = Express();
app.use(bodyParser.json());

const Storage = multer.diskStorage({
  destination(req, file, callback) {
    callback(null, './images');
  },
  filename(req, file, callback) {
    callback(null, `${file.fieldname}_${Date.now()}_${file.originalname}`);
  },
});

const upload = multer({ storage: Storage });

app.get('/', (req, res) => {
  res.status(200).send('You can post to /api/upload.');
});

app.post('/api/upload', upload.array('photo', 3), (req, res) => {
  console.log('file', req.files);
  console.log('body', req.body);
  res.status(200).json({
    message: 'success!',
  });
});

app.listen(3000, () => {
  console.log('App running on http://localhost:3000');
});

Son olarak, uygulamayı index.js node ile çalıştırabilirsiniz.

Şimdi başlamaya hazırız!

Resim Seçme

Bir resim yüklemeden önce, yükleyecek bir resmimiz olmalı! İşte burada react-native-image-picker devreye giriyor. Cihazımızdan bir görüntü seçmemize izin verecek.
mobile/App.js’yi aşağıdakilerle güncelleyebilirsiniz:

App.js

import React from 'react';
import { View, Text, Image, Button } from 'react-native';
import ImagePicker from 'react-native-image-picker';

export default class App extends React.Component {
  state = {
    photo: null,
  };

  handleChoosePhoto = () => {
    const options = {
      noData: true,
    };
    ImagePicker.launchImageLibrary(options, (response) => {
      if (response.uri) {
        this.setState({ photo: response });
      }
    });
  };

  render() {
    const { photo } = this.state;
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        {photo && (
          <Image
            source={{ uri: photo.uri }}
            style={{ width: 300, height: 300 }}
          />
        )}
        <Button title="Choose Photo" onPress={this.handleChoosePhoto} />
      </View>
    );
  }
}

Bu kod, kullanıcının resim galerisini açmasına ve bir fotoğraf seçmesine olanak tanır. Bir fotoğraf seçtiklerinde, uygulamada şu şekilde görüntülenecektir:

Request Body Oluşturma

Herhangi bir veri oluşturmak/güncellemek için daha önce getirme API’sini kullandıysanız, muhtemelen şöyle bir şey yapmışsınızdır:

example.js

fetch('MY_API_URL', {
  method: 'POST',
  body: JSON.stringify({
    userId: '123',
  }),
});

Bir görüntü yüklemek için bunun yerine verileri multipart/form-data kodlama türüne göre yüklememiz gerekir.

Bunu yapmak için FormData kullanarak isteğimizin gövdesini oluşturabiliriz.

Sunucumuzu kurduğumuzda, resmin fotoğraf anahtarında olacağını söyledik, bu yüzden gerekli tüm fotoğraf bilgilerini koyduğumuzdan emin olmamız gerekiyor. Ayrıca diğer ilişkili bilgileri (userId gibi) iletmenize de izin vereceğiz.

App.js

const createFormData = (photo, body) => {
  const data = new FormData();

  data.append('photo', {
    name: photo.fileName,
    type: photo.type,
    uri:
      Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', ''),
  });

  Object.keys(body).forEach((key) => {
    data.append(key, body[key]);
  });

  return data;
};

Önce FormData’yı başlatıyoruz ve ardından fotoğraf anahtarını ekliyoruz. Bu mesajın gövdesi, bunun işe yaraması için gereken minimum değerdir. Bir dosya adı, bir dosya türü ve ardından bir uri iletmemiz gerekiyor. Uri, görüntünün cihazda bulunduğu yerdir.

Çalışması için bu uri’ye platforma dayalı olarak biraz masaj yapmamız gerektiğini fark edeceksiniz. Esasen, sadece iOS’taki uri’den file:// soymak için kaynar.

Son olarak, uç noktaya iletmek istediğimiz herhangi bir ek veriyi (bu fotoğraf değil) döngüye alırız.

Resmin Yüklenmesi
Son olarak, fotoğrafı yükleyebiliriz.

Fotoğrafı yüklemek için bileşenimizde yeni bir işlev oluşturacağız.

App.js

handleUploadPhoto = () => {
  fetch('http://localhost:3000/api/upload', {
    method: 'POST',
    body: createFormData(this.state.photo, { userId: '123' }),
  })
    .then((response) => response.json())
    .then((response) => {
      console.log('upload succes', response);
      alert('Upload success!');
      this.setState({ photo: null });
    })
    .catch((error) => {
      console.log('upload error', error);
      alert('Upload failed!');
    });
};

Endpoint api/upload’da ve bir POST isteği bekliyor. Daha sonra daha önce belirtmek üzere kaydettiğimiz fotoğrafı createFormData fonksiyonuna geçiriyoruz.

Daha sonra getirmenin bize sağladığı söz zincirine girebiliriz. Önce yanıtı bir json nesnesine dönüştürüyoruz ve ardından fotoğrafın yüklendiği konusunda kullanıcıyı uyarıyoruz!

Görsel yüklenemezse, bu hatayı yakalar ve kullanıcıya görselin yüklenemediğini bildiririz.

Fotoğrafı gerçekten yüklemeden önce, bir kullanıcıya işlemi başlatmak için dokunabilecekleri bir düğme vermemiz gerekiyor.

App.js

export default class App extends React.Component {
  ...

  render() {
    const { photo } = this.state
    return (
      
        {photo && (
          
            
            
          
        )}
        
      
    )
  }
}

Şimdi, bir fotoğraf seçip yükle düğmesine bastığınızda, sunucuda/görüntülerde sunucuda yeni bir görüntünün göründüğünü görmelisiniz.

 

Kaynak:https://www.reactnativeschool.com/

React Native ile Mobil Uygulama Geliştirme – 15 – Blur Background View Oluşturma

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 15. kısmıdır. Bir önceki makalede (Part 14), React Native’de WebView oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı anlattım.
Bu makalede React Native Community Blur paketi ile Android ve iOS uygulamalarının arka plan görünümünü bulanık(blur) nasıl yapabileceğimizi öğreneceğiz.
Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.
Bu yazıda @react-native-community/blur olarak bilinen harika bir react yerel npm paketi hakkında bilgi edineceğiz. React Native Community Blur paketi, hem android hem de iOS uygulamalarına  bulanık arka plan görünümü oluşturmak için kullanılır. React Native Community Blur paketinde koyu, açık ve xlight olmak üzere temel olarak 3 tür bulanıklaştırma efekti vardır. Bugün bir react native uygulaması oluşturacak ve @react-native-community/blur paketini NPM sunucusunu kullanarak proje uygulamamıza yükleyeceğiz. Yüklemeyi bitirdikten sonra, react native ile bulanık görünüm yapma kodunu yazacaktık.
1. İlk adım, @react-native-community/blur paketini projemize yüklemektir. Bu nedenle, projenizin Kök dizinini Komut İstemi veya Terminal’de açın ve aşağıdaki komutu yürütün.

npm install --save @react-native-community/blur

2. Artık android’de yükleme işlemi için başka herhangi bir komut yürütmeniz gerekmiyor. Ancak iOS için kurulum işlemini tamamlamak için aşağıdaki komutu uygulamalıyız.

cd ios && pod install && cd ..

3. Şimdi bir sonraki adım, uygulama için kodlamaya başlamaktır. Bu nedenle, projenizin ana App.js dosyasını açın ve Projenize Görünüm, Stil Sayfası, Metin, Resim ve Bulanık Görünüm bileşenini içe aktarın.

import React from 'react';
import { View, StyleSheet, Text, Image } from 'react-native';
import { BlurView } from '@react-native-community/blur';

4. Ana dışa aktarma varsayılan Uygulama işlevsel bileşenimizi oluşturma.

export default function App() {
  return (
  );
}

5. Şimdi dönüş bloğunda ilk önce bir Kök Görünüm bileşeni -> Arka Plan Görüntüsü bileşeni -> BlurView Bileşeni yapacağız. Şimdi, Bulanıklaştırma Görünümü bileşenine hangi bulanıklaştırma efektini uyguladığımızı göstermek için bir Metin bileşeni yapacağız.
Burada temel olarak 3 tür BlurView efekti mevcuttur: –
1. dark
2. light
3. xlight
Mevcut Prop:
1. stil: – Bulanıklaştırma Görünümü bileşenine stil uygulamak için kullanılır.
2. blurType: – Bulanıklaştırma türünü ayarlamak için kullanılır, desteklenen değerler dark, light, xlight’tır.
3. blurAmount: – Bulanıklaştırma yoğunluğunu ayarlar.
4. lessTransparencyFallbackColor: – Yalnızca iOS, siyah, beyaz, #rrggbb, vb. – Erişilebilirlik ayarı ReduceTransparency etkinse kullanılacak arka plan rengi.

  return (
    <View style={styleSheet.MainContainer}>
      <Image
        source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2021/04/beach_new.jpg' }}
        style={styleSheet.image}
        key={'blurryImage'} />
      <BlurView
        style={styleSheet.blurView}
        blurType="light"  // Values = dark, light, xlight .
        blurAmount={10}
       // viewRef={this.state.viewRef}
        reducedTransparencyFallbackColor="white"
      />
      <Text style={{ fontSize: 34, color: 'white', fontWeight: 'bold', textAlign: 'center' }}> React Native Blur View Dark</Text>
    </View>
  );

6. Stil Oluşturma.

const styleSheet = StyleSheet.create({
  MainContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 12
  },
  blurView: {
    position: "absolute",
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },
  image: {
      position: "absolute",
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      resizeMode: 'cover',
      width: null,
      height: null,
  }
});

7. App.js dosyası için tam Kaynak Kodu: –

import React from 'react';
import { View, StyleSheet, Text, Image } from 'react-native';
import { BlurView } from '@react-native-community/blur';
export default function App() {
  return (
    <View style={styleSheet.MainContainer}>
      <Image
        source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2021/04/beach_new.jpg' }}
        style={styleSheet.image}
        key={'blurryImage'} />
      <BlurView
        style={styleSheet.blurView}
        blurType="light"  // Values = dark, light, xlight .
        blurAmount={10}
       // viewRef={this.state.viewRef}
        reducedTransparencyFallbackColor="white"
      />
      <Text style={{ fontSize: 34, color: 'white', fontWeight: 'bold', textAlign: 'center' }}> React Native Blur View Dark</Text>
    </View>
  );
}
const styleSheet = StyleSheet.create({
  MainContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 12
  },
  blurView: {
    position: "absolute",
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },
  image: {
      position: "absolute",
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      resizeMode: 'cover',
      width: null,
      height: null,
  }
});

Ekran görüntüleri:

Kaynak: https://reactnativecode.com/

React Native ile Mobil Uygulama Geliştirme – 14 – WebView Oluşturma

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 14. kısmıdır. Bir önceki makalede (Part 13), React Native’de Multi-Step Form oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı anlattım.

React Native’de web sitelerimizi webview ile  göstermeyi ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Bu yazıda React Native WebView ile web sitenizin görünümünü Ios ve Android uygulamanızda gösterebilmeyi anlatacağım. Web sitenizin URL’sini kullanarak bu işlemi yapacağımızdan, sitenizdeki herhangi bir değişiklik uygulamanıza anında yansıyacaktır.

1. Yeni bir proje oluşturun

react-native init ProjectName

2. Aşağıdaki bağımlılıkları yükleyin
Navigasyon ve react-native web görünümü için iki bağımlılık eklemeliyiz, navigasyon için en son react-navigasyon 5.0’ı kullanıyoruz. React-navigation 5.0 hakkında daha fazla bilgi edinmek için bu linke bakın. React-native-webview yüklemek için aşağıdaki komutu kullanın.

npm install --save react-native-webview

React-navigation 5.0 için aşağıdaki komutları kullanın.

İlk olarak, react-navigasyonu için aşağıdaki library’i kurun.

npm install @react-navigation/native

Ardından aşağıdaki komutu kullanarak destekleyici libraryleri kurun
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

3. WebViewScreen.js oluşturun
Bu ekranı birden çok kez kullanabilmemiz için WebViewScreen.js için ayrı ekran etkinliği oluşturacağız.

import React, { Component } from "react";

import { WebView } from "react-native-webview";    //<---Import this dependency

export default class WebViewScreen extends Component {
  constructor(props) {
    super(props);
    console.log(props.route.params);

    this.state = {
      url: props.route.params.url
    };
  }

  render() {
    return <WebView source={{ uri: this.state.url }} />;   //<---Pass url to webview
  }
}

Yapıcıdaki yukarıdaki ekranda, önceki ekrandan geçiş olan görünen URL’yi alıp durum değişkenine kaydedeceğiz ve yukarıdaki kodu gördüğümüz gibi kaynağa atlayarak web görünümünü görüntülemek için bu URL’yi kullanacağız.

4. WebView ekranını çağırma
Bu örnekte, aşağıdaki gibi Home.js eylem çubuğundan webViewScreen’i çağırıyorum

 const { navigation } = props;

  React.useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <TouchableOpacity
          onPress={() =>
            navigation.navigate("WebViewScreen", {               //<--- Call WebViewScreen and Pass URL
              url: "https://smality.com"
            })
          }
        >
          <Text style={{ color: "#FFFFFF", paddingHorizontal: 15 }}>
            Open WebView screen
          </Text>
        </TouchableOpacity>
      )
    });
  }, [navigation]);

5. App.js
React-navigation 5.0’da NavigationContainer’ı Kullanarak Ekranları tanımladığım App.js’mi ve createStackNavigator’ı kontrol edin.

import * as React from "react";
import { Text, View, Button } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";

import Home from "../screens/Home";
import WebViewScreen from "../screens/WebViewScreen";

const Stack = createStackNavigator();

function MainStackNavigator() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          gestureEnabled: true,
          headerStyle: {
            backgroundColor: "#3e78f4"
          },
          headerTitleStyle: {
            fontWeight: "bold"
          },
          headerTintColor: "#FFFFFF"
        }}
      >
        <Stack.Screen
          name="Home"
          component={Home}
          options={{ title: "Home Screen" }}
        />
       
        <Stack.Screen
          name="WebViewScreen"
          component={WebViewScreen}
          options={{ title: "React-native WebView" }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default MainStackNavigator;

Ekran Görüntüsü

Kaynak: https://www.techup.co.in/react-native-webview-example/

React Native ile Mobil Uygulama Geliştirme – 13 – Multi-step Form Oluşturma

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 13. kısmıdır. Bir önceki makalede (Part 12), React Native’de Context API ve Hooks ile Simple Toast oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı anlattım.

React Native’de multi-step form (step by step form) oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Bir müşteri için bir e-ticaret sitesi üzerinde çalışırken, ödeme sayfası için bir multi-step form üzerinde çalışmam gereken bir kısım vardı. İlk başta bunun için bir eklenti kullanabilirim diye düşünüyordum. Bu yüzden internette arama yaptım ama gereksinimlerimi karşılayan hiçbir şey bulamadım, bu yüzden kendim yaptım.

Fikir aslında çok basit, durum yönetimini kullanarak düğmelerin ve madde işaretlerinin nasıl görüntüleneceğini değiştirebilirsiniz. Ve biraz stil ile madde işaretlerinin nasıl çalıştığını vurgulayabilirsiniz. Onay işaretli yeşil madde işareti sayfanın tamamlandığını, gölgeli turuncu madde işareti o anda görüntülenen sayfayı belirtir ve ana hatları çizilen madde işaretleri henüz yapılmamış sayfaları gösterir. Siz kendi uygulamanıza göre kodları değiştirip deneyebilirsiniz.

import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { MaterialIcons, Ionicons } from '@expo/vector-icons';

export default class Settings extends React.Component {
	constructor(props){
		super(props);
		this.state ={
			currentStep: 1, /* using index 0 as starting point */
			steps: ['Review', 'Payment', 'Submit', 'Finish']
		}
	}
	
	render() {
		const styles = StyleSheet.create({
			centerElement: {justifyContent: 'center', alignItems: 'center'},
		});
		
		const { steps, currentStep } = this.state;
		
		return (
			<View style={{ flex: 1, flexDirection: 'column', backgroundColor: '#f6f6f6'}}>
				<View style={{flexDirection: 'row', backgroundColor: '#fff', marginBottom: 10}}>
					<TouchableOpacity style={[styles.centerElement, {width: 50, height: 50}]} onPress={() => {}}>
						<MaterialIcons name="arrow-back" size={25} color="#000" />
					</TouchableOpacity>
					<View style={[styles.centerElement, {height: 50}]}>
						<Text style={{fontSize: 18, color: '#000'}}>Checkout</Text>
					</View>
				</View>

				<View style={{alignItems: 'center'}}>
					<View style={{width: 280, height: 70}}>
						<View style={{alignItems: 'center'}}>
							<View style={{height: 2, backgroundColor: '#ee5e30', width: 180, position: 'absolute', top: 13, zIndex: 10}} />
						</View>
						<View style={{flexDirection: 'row', width: '100%', position: 'absolute', zIndex: 20}}>
							{steps.map((label, i) =>
								<View key={i} style={{alignItems: 'center', width: 70}}>
									{i > currentStep && i != currentStep && /* Not selected */
										<View style={{alignItems: 'center', justifyContent: 'center', width: 30, height: 30, backgroundColor: '#fff', borderWidth: 2, borderColor: '#ee5e30', borderRadius: 15, marginBottom: 10}}>
											<Text style={{fontSize: 15, color: '#ee5e30'}}>{i+1}</Text>
										</View>
									}
									{i < currentStep && /* Checked */
										<View style={{alignItems: 'center', justifyContent: 'center', width: 30, height: 30, backgroundColor: '#0faf9a', borderWidth: 2, borderColor: '#0faf9a', borderRadius: 15, marginBottom: 10}}>
											<Ionicons name="md-checkmark" size={20} color="#fff" />
										</View>
									}
									{i == currentStep && /* Selected */
										<View style={{alignItems: 'center', justifyContent: 'center', width: 30, height: 30, backgroundColor: '#ee5e30', borderWidth: 2, borderColor: '#ee5e30', borderRadius: 15, marginBottom: 10}}>
											<Text style={{fontSize: 13, color: '#ffffff'}}>{i+1}</Text>
										</View>
									}
									<Text style={{fontSize: 12}}>{label}</Text>
								</View>
							)}
						</View>
					</View>
				</View>
				
				<View style={{backgroundColor: '#fff'}}>
					{currentStep == 0 &&
						<View style={{height: 200, alignSelf: 'center'}}>
							<Text style={{fontSize: 30}}>Step 1</Text>
						</View>
					}	
					{currentStep == 1 &&	
						<View style={{height: 200, alignSelf: 'center'}}>
							<Text style={{fontSize: 30}}>Step 2</Text>
						</View>
					}	
					{currentStep == 2 &&	
						<View style={{height: 200, alignSelf: 'center'}}>
							<Text style={{fontSize: 30}}>Step 3</Text>
						</View>
					}	
					{currentStep == 3 &&	
						<View style={{height: 200, alignSelf: 'center'}}>
							<Text style={{fontSize: 30}}>Step 4</Text>
						</View>
					}
					<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
						{currentStep > 0 ?
							<TouchableOpacity style={[styles.centerElement, {bottom: 10, left: 10, width: 80, height: 35, backgroundColor: '#ee5e30', elevation: 10, borderRadius: 20}]} onPress={() => {
								if(currentStep > 0){
									this.setState({currentStep: currentStep - 1});
								}
							}}>
								<Text style={{color: '#fff'}}>Back</Text>
							</TouchableOpacity>
							: <Text> </Text>
						}
						{(currentStep+1) < steps.length /* add other conditions here */ &&
							<TouchableOpacity style={[styles.centerElement, {bottom: 10, right: 10, width: 80, height: 35, backgroundColor: '#ee5e30', elevation: 10, borderRadius: 20}]} onPress={() => {
								if((currentStep+1) < steps.length){
									this.setState({currentStep: currentStep + 1});
								}
							}}>
								<Text style={{color: '#fff'}}>Next</Text>
							</TouchableOpacity>
						}
						{(currentStep+1) == steps.length /* add other conditions here */ &&
							<TouchableOpacity style={[styles.centerElement, {bottom: 10, right: 10, width: 80, height: 35, backgroundColor: '#ee5e30', elevation: 10, borderRadius: 20}]} onPress={() => {
								console.log('Finish');
							}}>
								<Text style={{color: '#fff'}}>Finish</Text>
							</TouchableOpacity>
						}
					</View>
				</View>
			</View>
		);
	}
}

 

Ekran Çıktısı:

Lütfen bize görüşlerinizi bildirmekten çekinmeyin.

Kaynaklar:

1-https://www.npmjs.com/package/react-native-multistep-forms

2-https://zaferayan.medium.com/react-nativede-stepper-form-nas%C4%B1l-yap%C4%B1l%C4%B1r-e1eb58e5f0f3

3-https://reactscript.com/animated-multi-step-form-for-react-native/

4-https://carlofontanos.com/react-native-wizard-stepper/

React Native ile Mobil Uygulama Geliştirme – 12 – Context API ve Hooks ile Simple Toast Oluşturma

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 12. kısmıdır. Bir önceki makalede (Part 11), React Native’de Hooks ve FlatList ile Search Bar eklemeyi ve mobil projelerimizde nasıl kullanacağımızı anlattım.

React Native’de Context API ve Hooks ile Simple Toast oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

React Native topluluğu, Toast adı verilen küçük mesajların gösterilmesini sağlayan çok sayıda kullanıma hazır kütüphane sunar. Ancak, bunu kendi başımıza uygulamak büyük bir çaba değil. Ek olarak, davranışlarının ve görünümlerinin tam kontrolünü elde ederiz. Context API ve hookları kullanarak böyle bir çözümü zaman kaybetmeden uygulayabiliriz.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Her şeyden önce, create context ve Provide bileşeni oluşturmamız gerekiyor.

import React, { createContext, useState, useEffect, useRef, useCallback } from 'react';

const initialToast = {
  message: '',
  type: null,
  visible: false,
};

export const ToastContext = createContext({});

export const ToastProvider = ({children}) => {
  const [toast, setToast] = useState(initialToast);
  const timeout = useRef();

  const show = useCallback(args => {
    setToast({...initialToast, visible: true, ...args});
  }, []);

  const hide = useCallback(() => {
    setToast({...toast, visible: false});
  }, [toast]);

  return (
    <ToastContext.Provider
      value={{
        hide,
        show,
        toast,
      }}>
      {children}
    </ToastContext.Provider>
  );
};

Bu context’te 3 adet anahtarımız var. İki tanesi toast mesajın görünürlülüğünü ve gizliğini sağlamak için, bir taneside toast mesajın state’ini almak içindir.

Şimdi Consumer bileşeni oluşturmamız gerekiyor:

import React, {useContext, useEffect, useRef} from 'react';
import {ToastContext} from './ToastContext';
import {
  Text,
  Animated,
  Easing,
  TouchableOpacity,
  StyleSheet,
} from 'react-native';

export const Toast = () => {
  const {toast, hide} = useContext(ToastContext);
  const translateYRef = useRef(new Animated.Value(-100));

  useEffect(() => {
    if (toast.visible) {
      Animated.timing(translateYRef.current, {
        duration: 300,
        easing: Easing.ease,
        toValue: 100,
        useNativeDriver: true,
      }).start();
    } else {
      Animated.timing(translateYRef.current, {
        duration: 450,
        easing: Easing.ease,
        toValue: -100,
        useNativeDriver: true,
      }).start();
    }
  }, [toast]);

  return (
    <Animated.View
      style={[
        styles.toast,
        {transform: [{translateY: translateYRef.current}]},
      ]}>
      <TouchableOpacity onPress={hide} style={styles.content}>
        <Text style={styles.toastMessage}> {toast.message}</Text>
      </TouchableOpacity>
    </Animated.View>
  );
};

export default Toast;

Burada mevcut toast durumunu almak için useContext hooks kullanıyoruz ve animasyonu useEffect hooks kullanarak çalıştırıyoruz. Ek olarak, kullanıcının Toast’ı tıkladığında kapatmasına izin veriyoruz.

Toast bileşenimize bazı stiller ekleyelim:

const styles = StyleSheet.create({
  toast: {
    borderRadius: 4,
    marginHorizontal: 16,
    padding: 4,
    position: 'absolute',
    top: 0,
    zIndex: 2,
    right: 0,
    left: 0,
    backgroundColor: '#ff3f3f',
  },
  content: {
    alignItems: 'center',
    flexDirection: 'row',
    justifyContent: 'center',
    minHeight: 32,
    width: '100%',
  },
  toastMessage: {
    color: '#fff',
    fontWeight: '600',
    fontSize: 12,
    letterSpacing: 0.26,
    marginHorizontal: 10,
  },
});

Ancak, ToastProvider’ın içine useEffect hook’u ekleyerek Toast sağlayıcımıza otomatik gizleme ekleyebiliriz.

useEffect(() => {
    if (toast.visible) {
      timeout.current = setTimeout(hide, 1500);
      return () => {
        if (timeout.current) {
          clearTimeout(timeout.current);
        }
      };
    }
  }, [hide, toast]);

Şimdi provider ve consumer’u uygulamaya bağlayabiliriz:

import React from 'react';
import AppNavigation from './AppNavigation';
import {ToastProvider} from './ToastContext';
import Toast from './Toast';

const App = () =>  (
  <ToastProvider>
    <Toast />
    <AppNavigation />
  </ToastProvider>
);

export default App;

Evet! Provider içine Consumer girişini koyabileceğimizi ve context’e yalnızca göster / gizle yöntemini gösterebileceğimizi biliyorum, ancak daha esnek bir çözüme sahip olmak istiyorum (Consumer’u uygulama yapısında istediğim yere koyabilirim)

Artık Tostumuzu istediğimiz ekrandan gösterebiliriz:

import React, {useContext} from 'react';
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native';
import {ToastContext} from './ToastContext';

const HomeScreen = () => {
  const {show} = useContext(ToastContext);

  return (
    <View style={styles.container}>
      <TouchableOpacity onPress={() => show({message: 'Ama simple Toast!'})}>
        <Text>Show Toast</Text>
      </TouchableOpacity>
    </View>
  );
};

export default HomeScreen;

const styles = StyleSheet.create({
  container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
});

Ekran Çıktısı:

Lütfen bize görüşlerinizi bildirmekten çekinmeyin.

Kaynak

https://selleo.com

 

React Native ile Mobil Uygulama Geliştirme – 11 – Hooks ve FlatList ile Search Bar Ekleme

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 11. kısmıdır. Bir önceki makalede (Part 10), React Native’de Drag & Drop bileşenini oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı anlattım.

React Native’de Hooks ve FlatList Kullanarak Search Bar bileşenini eklemeyi ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

React Native ile mobil uygulamalar geliştirirken verileri görüntülemek için yaygın bir kullanım durumu, bir liste biçimindedir.

React Native’de liste oluşturmanın iki yaygın yolu vardır: ScrollView ve FlatList. Framework’ün API’sindeki bu bileşenlerin her birinin kendi gücü vardır.

Bu makalede, verileri almak, verileri görüntülemek ve bir arama çubuğu eklemek için FlatList tarafından sağlanan farklı unsurları inceleyelim.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Expo tabanlı yeni bir proje oluşturmak için, bir terminal penceresi açın ve aşağıdaki komutları açıklanan sırayla çalıştırın.

Proje dizini oluşturulduktan sonra lodash.filter’ı kurduğunuzdan emin olun. Paketi, daha sonra liste işlevinden bir arama eklerken verileri filtrelemek için kullanacağız.

npx expo init [Project Name]

# choose a template when prompted
# this example is using the 'blank' template

# after the project directory has been generated

cd [Project Name]

# install dependency
yarn add lodash.filter

FlatList Bileşenini Kullanma

React Native FlatList, genel performansı düşürmeden büyük miktarda veriden oluşan kaydırma listeleri oluşturmanın etkili bir yoludur. Büyük veri dizileri için optimize edilmiştir çünkü yalnızca ekranda görüntülenen bir dizi öğeyi oluşturur. Bir veri listesinde gezinirken, bileşen monte edildikten hemen sonra tüm verileri oluşturan ScrollView ile karşılaştırıldığında dahili durum korunmaz. Bu, ScrollView’daki tüm verilerin aygıtın belleğine eklendiği ve büyük miktarda veri işlenirken performansın düşmesine neden olabileceği anlamına gelir.

FlatList’e bir dizi veri iletmek, veri listesini nasıl görüntüleyebileceğinizdir. Bunun nasıl çalıştığını görelim. Örneğin, App.js’yi açın ve işlev bileşeninden önce aşağıdaki veri dizisini ekleyin.

const data = [
  { id: '1', title: 'First item' },
  { id: '2', title: 'Second item' },
  { id: '3', title: 'Third item' },
  { id: '4', title: 'Fourth item' }
];

Ardından, FlatList’i App.js dosyasında içe aktarın.

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

FlatList, bir veri listesini görüntülemek için gerekli olan üç birincil props kullanacak:

data: bir liste oluşturmak için kullanılan bir veri dizisi. Dizi, eleman olarak birden çok nesneden oluşur.
keyExtractor: FlatList’e, dizinin tek tek öğeleri için benzersiz bir tanımlayıcı veya kimlik kullanmasını söyler.
renderItem: veri dizisinden tek bir öğeyi alan ve onu kullanıcı arayüzünde işleyen bir işlev.

Ardından, bu veri listesini döndürmek için Uygulama bileşenini değiştirin.

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Basic FlatList Example</Text>
      <FlatList
        data={data}
        keyExtractor={item => item.id}
        renderItem={({ item }) => (
          <View style={styles.listItem}>
            <Text style={styles.listItemText}>{item.title}</Text>
          </View>
        )}
      />
    </View>
  );
}

Aşağıdaki styles nesnesini ekleyin.

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f8f8',
    alignItems: 'center'
  },
  text: {
    fontSize: 20,
    color: '#101010',
    marginTop: 60,
    fontWeight: '700'
  },
  listItem: {
    marginTop: 10,
    padding: 20,
    alignItems: 'center',
    backgroundColor: '#fff',
    width: '100%'
  },
  listItemText: {
    fontSize: 18
  }
});

Şimdi emülatöre geri dönün ve veri dizisindeki tüm nesnelerin artık bir liste şeklinde görüntülendiğini göreceksiniz. FlatList’i kullanmak, organize verileri görüntülemek için minimum çaba gerektirir.

FlatList’te bir API’den veri alma

FlatList, mobil uygulamanın verileri nasıl getirdiğini umursamıyor. Önceki bölümde, bir dizi veriyle nasıl alay edileceğini ve bir liste olarak nasıl kullanılacağını öğrendik. Bu bölümde, verileri bir uzak API kaynağından alalım ve verileri görüntülemek için aynı kalıbı (önceki bölümde olduğu gibi) takip edelim.

Yan Not: Uzak bir API kaynağı için, Random User Placeholder API‘yi kullanacağım.

Bu bölümde kullanacağımız tüm gerekli bileşenleri içe aktararak başlayın. Aşağıdaki içe aktarma ifadelerini aşağıda gösterildiği gibi güncelleyin:

import React, { useState, useEffect } from 'react';
import {
  StyleSheet,
  Text,
  View,
  FlatList,
  ActivityIndicator,
  Image
} from 'react-native';

Ardından, verileri sabit olarak almak için API endpoint URL’sini tanımlayın.

const API_ENDPOINT = `https://randomuser.me/api/?seed=1&page=1&results=20``;

API endpoint HTTP isteği şimdilik ilk 20 sonucu getirecek.

React Hook useState’i kullanarak App bileşeninin içinde üç durum değişkeni tanımlayın. isLoading durum değişkeninin boolean değeri varsayılan olarak false olacaktır. Amacı, veriler API endpoint’den getirilirken bir yükleme göstergesi görüntülemektir.

Veri değişkeni varsayılan olarak boş bir diziye sahip olacaktır. Bu durum değişkenini kullanarak, FlatList bir veri listesi görüntülemek için doldurulur.

Son durum değişkeni olan error, varsayılan bir null değerine sahip olacak. Yalnızca verileri alırken bir hata olduğunda güncellenecektir.

export default function App() {
  const [isLoading, setIsLoading] = useState(false);
  const [data, setData] = useState([]);
  const [error, setError] = useState(null);

  // ...
}

Sonra, React Hook useEffect’i ve JavaScript’ten alma API’sini kullanarak, verileri API_ENDPOINT’ten alalım. App bileşeninin içindeki durum değişkenlerini tanımladıktan sonra aşağıdakileri ekleyin.

UseEffect başlatıldığında yükleme değişkeni true olarak ayarlanır. Bu değişkenin boolean değeri, yalnızca verilerin getirilmesi tamamlandığında veya bir hata olduğunda false olarak ayarlanır. Aşağıdaki setData, veri değişkenini bir veri dizisi ile güncelliyor.

export default function App() {
  // state variables defined

  useEffect(() => {
    setIsLoading(true);

    fetch(API_ENDPOINT)
      .then(response => response.json())
      .then(results => {
        setData(results);
        setIsLoading(false);
      })
      .catch(err => {
        setIsLoading(false);
        setError(err);
      });
  }, []);
  // ...
}

Ardından, her biri iki farklı senaryo için bir JSX döndüren iki if koşulu ekleyin. İlk olarak, veriler getirilirken bir yükleme göstergesi gösterilir. İkinci olarak, bir hata olduğunda bir hata mesajı görüntülenir.

export default function App() {
  // state variables defined

  // fetch data using useEffect

  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" color="#5500dc" />
      </View>
    );
  }

  if (error) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text style={{ fontSize: 18}}>
          Error fetching data... Check your network connection!
        </Text>
      </View>
    );
  }
  // ...
}

Ardından, kullanıcı avatarını ve API endpoint’den getirilen kullanıcının adını görüntülemek için FlatList’i güncelleyin.

export default function App() {
  // ...

  return (
    <View style={styles.container}>
      <Text style={styles.text}>Favorite Contacts</Text>
      <FlatList
        data={data}
        keyExtractor={item => item.first}
        renderItem={({ item }) => (
          <View style={styles.listItem}>
            <Image
              source={{ uri: item.picture.thumbnail }}
              style={styles.coverImage}
            />
            <View style={styles.metaInfo}>
              <Text style={styles.title}>{`${item.name.first} ${
                item.name.last
              }`}</Text>
            </View>
          </View>
        )}
      />
    </View>
  );
}

Styles nesnesini de güncellemeyi unutmayın.

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f8f8',
    alignItems: 'center'
  },
  text: {
    fontSize: 20,
    color: '#101010',
    marginTop: 60,
    fontWeight: '700'
  },
  listItem: {
    marginTop: 10,
    paddingVertical: 20,
    paddingHorizontal: 20,
    backgroundColor: '#fff',
    flexDirection: 'row'
  },
  coverImage: {
    width: 100,
    height: 100,
    borderRadius: 8
  },
  metaInfo: {
    marginLeft: 10
  },
  title: {
    fontSize: 18,
    width: 200,
    padding: 10
  }
});

Bu adımdan sonra alacağımız bir FlatList kullanılarak görüntülenen kişilerin listesi aşağıdadır.

Veriler getirilirken yüklenme göstergesi burada.

Ve aşağıda, uygulamanın verileri getiremediği senaryo verilmiştir.

Search Bar Ekleme

Bu bölümde, mevcut FlatList’in en üstünde bir arama çubuğu oluşturalım. Bir arama çubuğunu görüntülemek için ListHeaderComponent adlı bir destek sağlar.

Uygulama bileşenini düzenlemeye başlamadan önce, bu adımda gerekli olan gerekli içe aktarma ifadelerini ekleyelim. React-native’den TextInput için içe aktarmayı ekleyin. Ayrıca lodash.filter dosyasını içe aktarın.

import {
  StyleSheet,
  Text,
  View,
  FlatList,
  ActivityIndicator,
  Image,
  TextInput
} from 'react-native';
import filter from 'lodash.filter';

Aşağıda gösterildiği gibi FlatList için prop ekleyin

<FlatList
  ListHeaderComponent={renderHeader}
  // ... rest of the props remain same
/>

Ardından, aşağıdaki JSX’i döndürecek renderHeader işlevini tanımlayın:

export default function App() {
  //...
  function renderHeader() {
    return (
      <View
        style={{
          backgroundColor: '#fff',
          padding: 10,
          marginVertical: 10,
          borderRadius: 20
        }}
      >
        <TextInput
          autoCapitalize="none"
          autoCorrect={false}
          clearButtonMode="always"
          value={query}
          onChangeText={queryText => handleSearch(queryText)}
          placeholder="Search"
          style={{ backgroundColor: '#fff', paddingHorizontal: 20 }}
        />
      </View>
    );
  }
// … render JSX below
}

İşte bu adımdan sonra emülatördeki çıktı.

Ardından, iki durum değişkeni daha ekleyin. İlk olarak, sorgu, veri listesinde arama yapmak için kullanıcı tarafından sağlanan herhangi bir girdiyi takip edecektir. Varsayılan bir boş dizge değerine sahiptir. İkinci olarak, verileri filtrelemek için kullanılacak olan API’den verileri tutmak için başka bir değişken ekleyin.

const [query, setQuery] = useState('');
const [fullData, setFullData] = useState([]);

Tüm Data dizisini doldurmak için side-effect olarak useEffect’i güncelleyin.

useEffect(() => {
  setIsLoading(true);

  fetch(API_ENDPOINT)
    .then(response => response.json())
    .then(response => {
      setData(response.results);

      // ADD THIS
      setFullData(response.results);

      setIsLoading(false);
    })
    .catch(err => {
      setIsLoading(false);
      setError(err);
    });
}, []);

Ardından, search bar’ı işleyecek olan handleSearch adında bir işleyici yöntemi ekleyin. Varsayılan olarak, sorgu olarak sağlanan arama terimini küçük harfe biçimlendirecektir. Kullanıcının adı, durum değişkeni fullData’dan filtrelenirken durum değişkeni verileri, doğru kullanıcıyı oluşturmak için aramadan sonra nihai sonuçları saklar.

İçerme işleyicisi yöntemi sorguyu arayacaktır. Kullanıcının adı ve soyadı ve handleSearch() ‘den küçük harfe biçimlendirilmiş sorgu olmak üzere iki parametre kabul eder.

const handleSearch = text => {
  const formattedQuery = text.toLowerCase();
  const filteredData = filter(fullData, user => {
    return contains(user, formattedQuery);
  });
  setData(filteredData);
  setQuery(text);
};

const contains = ({ name, email }, query) => {
  const { first, last } = name;

  if (first.includes(query) || last.includes(query) || email.includes(query)) {
    return true;
  }

  return false;
};

Emülatörde, bu sorguya dayalı sonuçları almak için bir arama sorgusu.

Bu makalenin odak noktası, FlatList bileşeninin sağladığı farklı donanımlara aşina olmanızı sağlamaktı.

Daha iyi sonuçlar için bir API endpoint’den veri alırken Algolia gibi güçlü bir arama sağlayıcısının kullanılması önerildiğini unutmayın.

Son olarak, hassas mantık içeren ticari React Native uygulamaları geliştiriyorsanız özel dikkat göstermeyi unutmayın. Kılavuzumuzu izleyerek onları kod hırsızlığına, kurcalanmaya ve ters mühendisliğe karşı koruyabilirsiniz.

Lütfen bize görüşlerinizi bildirmekten çekinmeyin.

Kaynak

1-https://blog.jscrambler.com/add-a-search-bar-using-hooks-and-flatlist-in-react-native/

React Native ile Mobil Uygulama Geliştirme – 10 – Drag & Drop Bileşenini Oluşturma

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 10. kısmıdır. Bir önceki makalede (Part 9), React Native’de Redux Kullanımı ve mobil projelerimizde nasıl kullanacağımızı anlattım.

React Native’de Drag & Drop bileşenini oluşturmayı ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

Bir sonraki React Native uygulamam için beyin fırtınası yaparken, işte ilk adım, bir Drag & Drop bileşenini oluşturabilmek için hareketi izleyen bir API olup olmadığını görmek istedim.
Neyse ki bulması çok zor olmadı: PanResponder’a sahibiz! Bununla hareketi soyut bir durum olarak izleyebilir ve kullanıcı arayüzümüzü buna göre güncelleyebiliriz.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Nasıl bir uygulama yapmak istediğimizin kafamızda netleşmesi için aşağıdaki görsele bakabilirsiniz.

Drag Bileşen Oluşturma

PanResponder API belgelerini takip etmenin biraz zor olduğunu buldum, ancak bu örnek ve animasyon kılavuzu gitmeme yardımcı oldu. PanResponder sınıfını içe aktardıktan sonra, componentWillMount() yaşam döngüsü yönteminde .create yöntemiyle başlatırsınız. Bunu constructor() da yazabilirsiniz.

import React, { Component } from "react";
import {
  StyleSheet,
  View,
  PanResponder,
  Animated
} from "react-native";

export default class Draggable extends Component {
  constructor() {
    super();
    this.state = {
      pan: new Animated.ValueXY()
    };
  }

  componentWillMount() {
    // Add a listener for the delta value change
    this._val = { x:0, y:0 }
    this.state.pan.addListener((value) => this._val = value);
    // Initialize PanResponder with move handling
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (e, gesture) => true,
      onPanResponderMove: Animated.event([
        null, { dx: this.state.pan.x, dy: this.state.pan.y }
      ])
      // adjusting delta value
      this.state.pan.setValue({ x:0, y:0})
    });
  }

  render() {
    const panStyle = {
      transform: this.state.pan.getTranslateTransform()
    }
    return (
        <Animated.View
          {...this.panResponder.panHandlers}
          style={[panStyle, styles.circle]}
        />
    );
  }
}

let CIRCLE_RADIUS = 30;
let styles = StyleSheet.create({
  circle: {
    backgroundColor: "skyblue",
    width: CIRCLE_RADIUS * 2,
    height: CIRCLE_RADIUS * 2,
    borderRadius: CIRCLE_RADIUS
  }
});

this.panResponder = PanResponder.create(), panResponder’ı başlatır ve bir referans oluşturur. Bunu <Animate.View> bileşenimizde, bir sahne grubundan geçiyormuş gibi {… this.panResponder.panHandlers} ‘ı geçirerek kullanırız.
PanResponder.create() içinde onStartShouldSetPanResponder’ı true olarak ayarladık, böylece panResponder dokunma geri bildirimlerine yanıt verecek. Sonra onPanResponderMove’a bir Animated.event iletiriz: kullanıcının hareket ettiği Animated.View circle bileşenimizin konumunu güncellemek için.
Çevremizin konumunu elde etmek için hesaplanan animasyon değerini this.state.pan.getTranslateTransform() ‘dan alıp Animated.View’a aktardığımız bir dönüştürme stili oluşturmak için kullanırız.
Son olarak, öğenin ikinci dokunuşta atlamaması için delta değerini ayarlıyoruz.
Bu noktada, kullanıcının etkileşime girebileceği sürüklenebilir bir dairemiz var:

Çemberi İlk Konumuna Geri Döndürmek

Bileşeni bıraktıklarında dairenin orijinal konumuna geri dönmesini istiyoruz. Bunu yapmak için onPanResponderRelease’i kullanarak kullanıcı arayüzüne kullanıcı bıraktığında nasıl yanıt vereceğini bildiririz.

componentWillMount() {
  ...
    this.panResponder = PanResponder.create({
      ...
      onPanResponderRelease: (e, gesture) => {
        Animated.spring(this.state.pan, {
          toValue: { x: 0, y: 0 },
          friction: 5
        }).start();
      }
    });

Dairemiz şimdi ilk konumuna geri dönüyor:

Bırakma Alanının Oluşturulması

Artık sürüklemeye sahibiz, bırakmaya ihtiyacımız var. Bırakma alanımızla başka bir bileşen oluşturuyoruz ve içinde Sürüklenebilir bileşenimizi kullanıyoruz:

import React, { Component } from "react";
import { StyleSheet, View, Text } from "react-native";
import Draggable from "./Draggable";

export default class Screen extends Component {
  render() {
    return (
      <View style={styles.mainContainer}>
        <View style={styles.dropZone}>
          <Text style={styles.text}>Drop them here!</Text>
        </View>
        <View style={styles.ballContainer} />
        <View style={styles.row}>
          <Draggable />
          <Draggable />
          <Draggable />
          <Draggable />
          <Draggable />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  mainContainer: {
    flex: 1
  },
  ballContainer: {
    height:200
  },
  row: {
    flexDirection: "row"
  },  
  dropZone: {
    height: 200,
    backgroundColor: "#00334d"
  },
  text: {
    marginTop: 25,
    marginLeft: 5,
    marginRight: 5,
    textAlign: "center",
    color: "#fff",
    fontSize: 25,
    fontWeight: "bold"
  }
});

Ardından Draggable, onPanResponderRelease işleyicisine biraz mantık ekliyoruz ve bırakma alanında olup olmadığımızı belirlemek için bir işlev ekliyoruz. Not: Burada ekrandaki bırakma bölgesinin konumu hakkında varsayımlarda bulunuyoruz.

...
  constructor()
    super.props();
    this.state = {
      showDraggable: true,
      dropAreaValues: null,
      pan: new Animated.ValueXY(),
      opacity: new Animated.Value(1)
    };
  }
  componentWillMount() {
    ...
    this.panResponder = PanResponder.create({
      ...
      onPanResponderRelease: (e, gesture) => {
        if (this.isDropArea(gesture)) {
          Animated.timing(this.state.opacity, {
          toValue: 0,
          duration: 1000
        }).start(() =>
          this.setState({
             showDraggable: false
          })
        );
      } else {
        Animated.spring(this.state.pan, {
          toValue: { x: 0, y: 0 },
          friction: 5
        }).start();
      }
    }
  isDropArea(gesture) {
    return gesture.moveY < 200;
  }

Uygulamayı çalıştırdığımızda aşağıdaki gibi bir görüntü ortaya çıkar.

PanResponder API’si ilk başta benim için biraz korkutucuydu, ancak şimdi bu, herkesin uygulamalarında kullanıcı deneyimini daha iyi hale getirmek için kullanabileceği harika bir API olduğunu düşünüyorum.
Umarım bu makale, sorularınız veya endişeleriniz olan yorumlarda size ulaşmanıza yardımcı olmuştur. Okuduğunuz için teşekkürler ve iyi kodlamalar!

Lütfen bize görüşlerinizi bildirmekten çekinmeyin.

Kaynak

1-https://blog.reactnativecoach.com/creating-draggable-component-with-react-native-132d30c27cb0

React Native ile Mobil Uygulama Geliştirme – 9 – React Native’de Redux Kullanımı

“React Native ile Mobil Uygulama Geliştirme” başlıklı makalelerimizden bir yenisini daha sizlerle paylaşmak istiyorum. Bu makale, bir dizi makaleden oluşacak olan serisinin 9. kısmıdır. Bir önceki makalede (Part 8), React Native’de Tab Navigation Kullanımı ve mobil projelerimizde nasıl kullanacağımızıanlattım.

React Native’de Redux Kullanımı ve mobil projelerimizde nasıl kullanacağımızı öğreneceğiz.

Redux’la kullanacağımız bazı nesneler ya da kavramlar var. Öncelikle onlardan kısaca bahsetmek gerekebilir. Mantığını anlayabilmemiz için ihtiyacımız olan üç ana kavram; “store”, “reducer” ve “action” diyebiliriz.

store: Redux kütüphanesiyle birlikte yaratacağımız verilerin tutulacağı alan diyebiliriz. Uygulamamızda tek bir adet “store”umuz olacak ve state’lerimizi bu store’un içinde depolayacağız.

reducer: Action’dan gelen verileri süzgeçleyip store’da belirtilen veriyi güncellememizi sağlayan bir araç.

action: Reducer’lara ulaşarak onları tetikleyen, store’daki güncellemesi gereken veriyi yollan bir araç. Neyi güncellemesi gerektiğini adlandırırken “type” ile belirtmemiz gerekirken, değiştirmesi gereken veriyi payload’larla taşır.

Daha önceki makaleleri okumadıysanız, lütfen buradan başlayın.

Redux, JavaScript uygulamaları için öngörülebilir bir state konteynirdir. Redux sizin için yeniyse, Redux ile ilgili bu yazımızı okumanızı öneririm.

Bu makalede, bir React Native uygulamasında Redux kullanarak kullanıcı verilerini nasıl saklayacağınızı öğreneceksiniz. Uygulama, bir dizi bağlı arkadaşın görüntülendiği bir HomeScreen ve eklenecek potansiyel arkadaşların bir listesini görüntüleyen bir FriendsScreen’e sahip sahte bir sosyal ağdır. Durumu iki ekran arasında paylaşmak için Redux kullanacaksınız.

İlk önce MySocialNetwork adında bir React Native Mobil proje oluşturalım ve konsolda proje dizinine gidelim. Ardından, projede redux ve react-redux kitaplıklarını kurun:

cd MySocialNetwork
npm install
npm install redux@4.0.5 react-redux@7.2.1

Projeniz şimdi kuruldu ve bağımlılıklarınız kuruldu. Projenin kök dizininde FriendsReducer.js isimli bir dosya oluşturalım ve aşağıdaki kodları yazalım.

import { combineReducers } from 'redux';

const INITIAL_STATE = {
  current: [],
  possible: [
    'Alice',
    'Bob',
    'Sammy',
  ],
};

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    default:
      return state
  }
};

export default combineReducers({
  friends: friendsReducer
});

Bu dosyada, sosyal ağınıza eklemek için olası arkadaşlarınızla bir INITIAL_STATE değişkeni oluşturursunuz. Ardından, friendsReducer’ı arkadaşlar adlı bir özellik olarak dışa aktarıyorsunuz.

Actions, uygulamanızdan Redux deposuna veri gönderen bilgi yüklerini temsil eden JavaScript nesneleridir.

Actions bir türü ve isteğe bağlı bir yükü vardır. Bu örnek, tür ADD_FRIEND olacak ve yük, mevcut arkadaşlar dizisine eklediğiniz bir arkadaşın dizi dizini olacaktır.

FriendsActions.js dosyasını projenin kök düzeyinde oluşturun:

export const addFriend = friendsIndex => (
  {
    type: 'ADD_FRIEND',
    payload: friendsIndex,
  }
);

Bir kullanıcı bir arkadaşa tıkladığında, bu kod friends.possible dizisinden friendsIndex’i alır. Şimdi bu arkadaşı friends.current dizisine taşımak için bu indeksi kullanmanız gerekecek.

FriendsReducer.js: dosyasına geri dönelim.

// ...

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case 'ADD_FRIEND':
      // Pulls current and possible out of previous state
      // We do not want to alter state directly in case
      // another action is altering it at the same time
      const {
        current,
        possible,
      } = state;

      // Pull friend out of friends.possible
      // Note that action.payload === friendIndex
      const addedFriend = possible.splice(action.payload, 1);

      // And put friend in friends.current
      current.push(addedFriend);

      // Finally, update the redux state
      const newState = { current, possible };

      return newState;

    default:
      return state
  }
};

// ...

Bu kod, mevcut ve olası arkadaşları önceki durumdan çıkarır. Array.splice(), arkadaşı olası arkadaşlar dizisinden alır. Array.push, arkadaşı mevcut arkadaş dizisine ekler. Değişiklikler yapıldıktan sonra durum güncellenir.

Artık bir reducer and ve bir action’imiz var. Reducer’u uygulamanıza uygulamanız gerekecek.

React Redux’ün Sağlayıcı bileşenini kullanarak uygulamanızın arkadaş durumunu sağlamanız gerekecektir.

App.js’yi açın:

ProvidercreateStore, ve friendsReducer import edin.

import 'react-native-gesture-handler';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import friendsReducer from './FriendsReducer';
import HomeScreen from './HomeScreen';
import FriendsScreen from './FriendsScreen';

// ...
// ...

const store = createStore(friendsReducer);

class App extends React.Component {
  // ...

  render() {
    return (
      <Provider store={store}>
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen
              name="Home"
              component={HomeScreen}
            />
            <Stack.Screen
              name="Friends"
              component={FriendsScreen}
            />
          </Stack.Navigator>
        </NavigationContainer>
      </Provider>
    )
  }
}

Artık arkadaşlarınıza uygulamanızdan erişilebilir, ancak onları yine de Ana Ekrana (HomeScreen) ve Arkadaşlar Ekranına (FriendsScreen) eklemeniz gerekir.

Bu adımda, mapStateToProps işlevi ile arkadaşlarınızı ekranlarınız için erişilebilir hale getireceksiniz. Bu işlev, FriendsReducer’daki durumu iki ekrandaki sahne öğelerine eşler.

HomeScreen.js ile başlayalım. HomeScreen.js dosyasını açın:

import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>You have (undefined) friends.</Text>

        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = (state) => {
  const { friends } = state
  return { friends }
};

export default connect(mapStateToProps)(HomeScreen);

Bu kod değişikliği, react-redux ekler ve arkadaşları HomeScreen’de kullanılabilir hale getirir.

Ardından, mevcut arkadaşlar için değerler ekleyin (this.props.friends.current):

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>You have { this.props.friends.current.length } friends.</Text>

        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }
}

Ana Ekranınız şimdi mevcut arkadaşların sayısını gösterecektir. Artık FriendsScreen’e geçebilirsiniz.

FriendsScreen.js’yi açın:

import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = (state) => {
  const { friends } = state
  return { friends }
};

export default connect(mapStateToProps)(FriendsScreen);

Bu kod değişikliği, react-redux ekler ve arkadaşları FriendsScreen’de kullanılabilir hale getirir.

Olası arkadaşlar için değerler ekleyin (props.friends.possible):

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        {
          this.props.friends.possible.map((friend, index) => (
            <Button
              key={ friend }
              title={ `Add ${ friend }` }
            />
          ))
        }

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

Artık Arkadaşlar Ekranına gittiğinizde, indirgeyiciden tüm olası arkadaşları göreceksiniz.
Son olarak, yeni Redux Arkadaş Ekle seçeneğini FriendsScreen.js’ye ekleyin:

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { StyleSheet, Text, View, Button } from 'react-native';
import { addFriend } from './FriendsActions';

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        {
          this.props.friends.possible.map((friend, index) => (
            <Button
              key={ friend }
              title={ `Add ${ friend }` }
              onPress={() =>
                this.props.addFriend(index)
              }
            />
          ))
        }

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

// ...

const mapDispatchToProps = dispatch => (
  bindActionCreators({
    addFriend,
  }, dispatch)
);

export default connect(mapStateToProps, mapDispatchToProps)(FriendsScreen);

Sosyal ağa iki arkadaş ekleyelim ve kullanıcının mevcut kaç arkadaşı olduğunu görmek için HomeScreen’e geri dönelim:

Bununla birlikte, tüm mantığı App.js’den Redux’a taşıdınız, bu da uygulamanızı özellikle kimlik doğrulama ve veritabanı entegrasyonu gibi daha fazla sayfa ve özellik ekledikçe çok daha esnek hale getiriyor.

Tamamlamadan önce kodu temizleyelim.

Artık Redux kullandığınıza göre, App.js’den geçtiğiniz desteğe artık ihtiyacınız olmayacak.

Eylem türlerinizi ayrı bir dosyada saklayarak temizliği bir adım daha ileri götürebilirsiniz.

‘ADD_FRIEND’ dizesini iki yerde kullanıyorsunuz: eylemde ve arkadaş azaltıcıda. Bu tehlikelidir, çünkü dizeyi bir yerde değiştirirseniz diğerinde değiştirmezseniz başvurunuzu bozabilirsiniz. Uygulamanız büyüdükçe, tüm bu işlem türlerini types.js adlı bir dosyada tutmak mantıklı hale gelir.

Types.js dosyasını kök seviyesinde oluşturun:

export const ADD_FRIEND = 'ADD_FRIEND';

Ardından, yeni ADD_FRIEND’yi kullanmak için FriendsActions.js’yi yeniden düzenleyelim.

import { ADD_FRIEND } from './types';

export const addFriend = friendsIndex => (
  {
    type: ADD_FRIEND,
    payload: friendsIndex,
  }
);

FriendsReducer.js dosyasındaki “ADD_FRIEND” değişkenini ADD_FRIEND değişkenine değiştirin:

import { combineReducers } from 'redux';
import { ADD_FRIEND } from './types';

// ...

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case ADD_FRIEND:
      // ...

    default:
      return state;
  }
};

Bu, uygulamayı daha az kırılgan hale getirir. Uygulamalarınızı geliştirirken, kodu birleştirmek ve kendinizi tekrar etmekten kaçınmak için fırsatların farkında olmalısınız.

Bu öğreticide, reduxreducersactions,ve ölçeklenebilir veri yönetimini (scalable data management) ele aldınız.

Verileri bir veritabanıyla senkronize tutmaktan, kimlik doğrulamasına ve kullanıcı izinlerini takip etmeye kadar Redux ile yapabileceğiniz çok daha fazla şey var.

Lütfen bize görüşlerinizi bildirmekten çekinmeyin.

Kaynak: https://www.digitalocean.com/community/tutorials/react-react-native-redux