II. Kiến thức nâng cao

Phần 1: React Native Animation và Image

1. React Native Animation

React Native Animations cung cấp thêm các hiệu ứng và trải nghiệm người dùng tuyệt vời cho ứng dụng. Các hoạt ảnh thể hiện chuyển động của các phần tử trong giao diện của bạn.

Có 2 loại hệ thống hoạt ảnh bổ sung trong React Native. Đó là:

  • Animated: Animated API để điều kiển một cách tương tác các giá trị. Nó tập trung vào mối quan hệ khai báo giữa các input và output. Nó có các phương thức start và stop để điều khiển việc thực thi các hoạt ảnh dựa trên thời gian.
    Animated export 4 thành phần hiệu ứng khác nhau đó là View, Text, Image và ScrollView. Chúng ta có thể tạo thành phần animated của riêng mình bằng Animated.createAnimatedComponent().
  • LayoutAnimated: LayoutAnimated sử dụng để tạo hiệu ứng cho các giao tác (transactions) của toàn bộ layout.

Các phương thức của Animated

MethodsDescription
Animated.timing()Tạo hiệu ứng cho giá trị theo thời gian sử dụng nhiều đường cong nới, hoặc sử dụng hàm của riêng nó.
Animated.event()Nó trực tiếp sắp xếp sự kiện vào các giá trị được tạo hiệu ứng.
Animated.spring()Tạo hiệu ứng cho giá trị. Nó theo dõi tốc độ của state để tạo ra các chuyển động mượt mà dưới dạng các cập nhật toValue .
Animated.decay()Nó khởi động hiệu ứng với một tốc độ ban đầu và chậm dần đến khi dừng lại.

React Native Animation Ví dụ 1 (Animated.timing())

Trong ví dụ này, chúng ta sẽ tạo hiệu ứng quay tròn trên hình ảnh sử dụng Animated.timing().

App.js

import React, { Component } from 'react';  
import {StyleSheet, AppRegistry,Text, View,Animated,Easing} from 'react-native';  
 
export default class DisplayAnImage extends Component {  
    constructor () {  
        super()  
        this.spinValue = new Animated.Value(0)//declare spinValue as a new Animated.Value and pass 0 (zero) in it.  
    }  
    componentDidMount () {  
        this.spin()  
    }  
    //create a spin method and call it from componentDidMount  
    spin () {  
        this.spinValue.setValue(0) //set spinValue to 0 (zero)  
        Animated.timing(    //calling Animated.timing() method, it takes two arguments:  
            this.spinValue, // value  
            {           // and config object  
                toValue: 1, //and setting spinValue to 1  
                duration: 4000, //within 4000 milliseconds  
                easing: Easing.linear
            }  
        ).start(() => this.spin())  
    }  
    render () {  
        const spin = this.spinValue.interpolate({  
            inputRange: [0, 1],  
            outputRange: ['0deg', '360deg']  
        })  
        return (  
            <View style={styles.container}>
                <Animated.Image
                    style={{  
                        width: 227,  
                        height: 200,  
                        transform: [{rotate: spin}] }}
                    source={require('MyReactNativeApp/img/react-logo.png')}
                />
            </View>
        )  
    }  
}  
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        justifyContent: 'center',  
        alignItems: 'center'
    }  
})  
// skip this line if you are using Create React Native App  
 
AppRegistry.registerComponent('DisplayAnImage', () => DisplayAnImage);

Phương thức interpolate() gọi bất kỳ Animated.Value nào. Nó sẽ thêm vào giá trị trước khi cập nhật property. Trong ví dụ trên, chúng ta đã sắp đặt từ 0 (zero) độ đến 360 độ.

Chúng ta truyền một inputRange [0,1] và lấy mảng outputRange['0deg', '360deg'].

Output:

React Native Animation Ví dụ 2 (Animated.timing())

Trong ví dụ này, chúng ta sẽ khai báo một giá trị có hiệu ứng duy nhất this.aninatedValue và sử dụng nó với interpolate để tạo nhiều hiệu ứng như: marginLeft, opacity, fontSize, và rotate. Chúng ta sẽ thêm vào các property dành cho tạo kiểu như opacity, margins, text sizes, và rotation.

App.js

import React, { Component } from 'react';  
import {StyleSheet, AppRegistry,Text, View,Animated,Easing} from 'react-native';  
 
export default class DisplayAnImage extends Component {  
    constructor () {  
        super()  
        this.animatedValue = new Animated.Value(0)  
    }  
    componentDidMount () {  
        this.animate()  
    }//animate method is call from componentDidMount  
    animate () {  
        this.animatedValue.setValue(0)  
        Animated.timing(  
            this.animatedValue,  
            {  
                toValue: 1,  
                duration: 2000,  
                easing: Easing.linear
            }  
        ).start(() => this.animate())  
    }  
 
    render() {  
        const marginLeft = this.animatedValue.interpolate({  
            inputRange: [0, 1],  
            outputRange: [0, 300]  
        })  
        const opacity = this.animatedValue.interpolate({  
            inputRange: [0, 0.5, 1],  
            outputRange: [0, 1, 0]  
        })  
        const movingMargin = this.animatedValue.interpolate({  
            inputRange: [0, 0.5, 1],  
            outputRange: [0, 300, 0]  
        })  
        const textSize = this.animatedValue.interpolate({  
            inputRange: [0, 0.5, 1],  
            outputRange: [18, 32, 18]  
        })  
        const rotateX = this.animatedValue.interpolate({  
            inputRange: [0, 0.5, 1],  
            outputRange: ['0deg', '180deg', '0deg']  
        })  
 
 
        return (  
            <View style={styles.container}>
                <Animated.View //returns Animated.View  
                    style={{  
                        marginLeft,  
                        height: 30,  
                        width: 40,  
                        backgroundColor: 'red'}} />
                <Animated.View
                    style={{  
                        opacity,  
                        marginTop: 10,  
                        height: 30,  
                        width: 40,  
                        backgroundColor: 'blue'}} />
                <Animated.View
                    style={{  
                        marginLeft: movingMargin,  
                        marginTop: 10,  
                        height: 30,  
                        width: 40,  
                        backgroundColor: 'orange'}} />
                <Animated.Text // returns Animated.Text  
                    style={{  
                        fontSize: textSize,  
                        marginTop: 10,  
                        color: 'green'}} >
                    Animated Text!  
                </Animated.Text>
                <Animated.View
                    style={{  
                        transform: [{rotateX}],  
                        marginTop: 50,  
                        height: 30,  
                        width: 40,  
                        backgroundColor: 'black'}}>
                    <Text style={{color: 'white'}}>Hello from TransformX</Text>
                </Animated.View>
            </View>
        )  
    }  
}  
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        paddingTop: 150
    }  
})  
// skip this line if you are using Create React Native App  
AppRegistry.registerComponent('DisplayAnImage', () => DisplayAnImage);

Output:

LayoutAnimation API

LayoutAnimation cho phép hiệu chỉnh, tạo và , cập nhật toàn bộ hiệu ứng. Nó sẽ được sử dụng cho tất cả các view trong chu kỳ render/layout kế tiếp.

LayoutAnimation khá là hữu dụng, nó có ít điều khiển hơn so với Animated và các thư viện hoạt ảnh khác.

Để sử dụng API này trong Android chúng ta cần phải đặt các cờ (flags) sau thông qua UIManager:

  • UIManager.setLayoutAnimationEnabledExperimental &&
  • UIManager.setLayoutAnimationEnabledExperimental(true);

Ví dụ về React Native LayoutAnimation

Trong ví dụ này, chúng ta sẽ taoh một thành phần TouchableOpacity và một thành phần View. Việc nhấn vào thành phần TouchableOpacity sẽ gọi phương thức the _onPress() và tạo hiệu ứng cho thành phần View bằng cách tăng chiều rộng và chiều cao của View thêm 15 đơn vị.

import React from 'react';  
import {  
    NativeModules,  
    LayoutAnimation,  
    Text,  
    TouchableOpacity,  
    StyleSheet,  
    View,  
} from 'react-native';  
 
const { UIManager } = NativeModules;  
 
UIManager.setLayoutAnimationEnabledExperimental &&  
UIManager.setLayoutAnimationEnabledExperimental(true);  
 
export default class App extends React.Component {  
    state = {  
        w: 100,  
        h: 100,  
    };  
 
    _onPress = () => {  
        // Animate the update  
        LayoutAnimation.spring();  
        this.setState({w: this.state.w + 15, h: this.state.h + 15})  
    }  
 
    render() {  
        return (  
            <View style={styles.container}>
                <View style={[styles.box, {width: this.state.w, height: this.state.h}]} />
                <TouchableOpacity onPress={this._onPress}>
                    <View style={styles.button}>
                        <Text style={styles.buttonText}>Press me!</Text>
                    </View>
                </TouchableOpacity>
            </View>
        );  
    }  
}  
 
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        alignItems: 'center',  
        justifyContent: 'center',  
    },  
    box: {  
        width: 200,  
        height: 200,  
        backgroundColor: 'blue',  
    },  
    button: {  
        backgroundColor: 'green',  
        paddingHorizontal: 20,  
        paddingVertical: 15,  
        marginTop: 15,  
    },  
    buttonText: {  
        color: '#fff',  
        fontWeight: 'bold',  
    },  
});

Output:

2. React Native Image

Thành phần Image sử dụng để hiển thị hình ảnh trên màn hình. Hình ảnh có thể được tải từ các nguồn khác nhau như các nguồn tài nguyên tĩnh, các tệp cục bộ tạm thòi, ổ đĩa cục bộ, các hình ảnh trên mạng,…

Các nguồn tài nguyên hình ảnh tĩnh

Các hình ảnh tĩnh được thêm vào ứng dụng bằng cách đặt nó trong thư mục source code và cung cấp đường dẫn của nó như sau:

1. <Img source="{require('./icon_name.png')}" />

Trong cú pháp trên, trình đóng gói (packager) sẽ tìm kiếm icon_name.png trong cũng một thư mục với thành phần mà yêu cầu nó. Để tải hình ảnh trên một nền tảng cụ thể, thì nó cần phải được đặt tên bằng cách xác định cụ thể như một phần mở rộng, chẳng hạn như icon_name.ios.png và icon_name.android.png.

Hình ảnh từ các nguồn tài nguyên của Ứng dụng tổng hợp

Các ứng dụng tổng hợp được xây dựng (UI) bằng cả React Native và code của nền tảng cũng có thể sử dụng các hình ảnh được đóng gói cùng với ứng dụng.

Hình ảnh được đi kèm thông qua các bảng kê asset Xcode hay trong các thư mục Android drawable được sử dụng mà không có các phần ở rộng của chúng:

<Image source={{uri: 'icon_name'}} style={{width: 60, height: 60}} />

Các hình ảnh trong thư mục Android assets, sử dụng scheme: asset:/ với phần mở rộng của hình ảnh:

<Image source={{uri: 'asset:/icon_name.png'}} style={{width: 60, height: 60}} />

Các hình ảnh trên mạng

Các hình ảnh động và hình ảnh trên mạng cũng có thể được hiển thị trong thành phần Image. Để truy cập hình ảnh trên mạng thì bắt buộc phải xác định cụ thể các chiều của hình ảnh một cách thủ công.

Nên sử dụng https để đáp ứng các yêu cầu App Transport Security trên iOS.

// GOOD  
<Image source={{uri: 'https://url_of_image.png'}}
       style={{width: 60, height: 60}} />
 
// BAD  
<Image source={{uri: 'https://url_of_image.png'}} />

Các hình ảnh Uri Data

Dữ liệu hình ảnh được mã hóa sử dụng scheme “data:” uri trong thành phần image. Hình ảnh dữ liệu sẽ được yêu cầu để xác định cụ thể các chiều của hình ảnh.

<Image
    style={{width: 66, height: 66}}
    source={{uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=='}}
/>

Hình nền thông qua phương pháp lồng nhau

Hình nền được đặt bằng thành phần ImageBackground. Nó cùng có các props như Image. Chúng ta có thể thêm bất kì thành phần con nào vào bên trên nó.

return (  
  <ImageBackground source={...} style={{width: '100%', height: '100%'}}>
    <Text>Inside</Text>
  </ImageBackground>
);

Ví dụ về React Native Image

App.js

import React, { Component } from 'react';  
import {StyleSheet, AppRegistry,Text, View, Image,ImageBackground } from 'react-native';  
 
export default class DisplayAnImage extends Component {  
    render() {  
        return (  
            <ImageBackground source = {{uri:'https://www.javatpoint.com/tutorial/react-native/images/react-native-tutorial.png'}}
                             style={{width: '100%', height: '100%'}}>
               <Image source={require('./favicon.png')} />
                <Image
                    source={require('/ReactNative/MyReactNativeApp/img/favicon.png')}
                />
 
                <Image
                    source={require('MyReactNativeApp/img/favicon.png')}
                />
                <Image source={{uri: 'asset:/images/favicon.png'}} style={{width: 60, height: 60}} />
                <Image source = {{uri:'https://www.javatpoint.com/images/logo/jtp_logo.png'}}
                       style = {{ width: '80%', height: 70 }}
                />
                <Image
                    style={{width: 60, height: 60}}
                    source={{uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg=='}}
                />
 
            </ImageBackground>
 
        );  
    }  
}  
// skip this line if using Create React Native App  
AppRegistry.registerComponent('DisplayAnImage', () => DisplayAnImage);

Output:

Phần 2: React Native APIs

1. React Native Alert

React Native Alert là một API được sử dụng để hiển thị các hộp thoại thông báo với các tiêu đề và nội dung cụ thể. Nó sử dụng một phương thức alert() để nhắc một hộp thoại thông báo. Hộp thoại Alert cung cấp 3 danh sách nút khác nhau (các tổ hợp của neutral, negative, và positive) để thực hiện các hành động. Nhấn bất kỳ nút nào sẽ gọi phương thức callback onPress và tắt thông báo đó đi. Ở mặc định, Alert chỉ có một nút positive (OK).

Alert có thể nhắc việc nhập thông tin được tạo ra bằng cách sử dụng AlertIOS. Điều này chỉ được hỗ trợ trên iOS.

React Native Alert trong iOS

Trong iOS, chúng ta có thể xác định cụ thể số nút. Mỗi nút có thể có một kiểu riêng, là một trong số default, cancel, hoặc destructive.

React Native Alert trong Android

Trong Android, nút của Alert được xác định bằng 3 nút. Những nút này là neutral, negative và positive. Các nút Alert được chia cụ thể thành 3 tổ hợp. Đó là:

  1. Nếu chỉ xác định một nút, thì đó sẽ là nút ‘positive’ (chẳng hạn như ‘OK’).
  2. Nếu xác định 2 nút, thì sẽ là ‘negative’ và ‘positive’ (chẳng hạn như ‘Cancel’ và ‘OK’).
  3. Xác định 3 nút sẽ bao gồm cả ‘neutral’, ‘negative’, ‘positive’ (chẳng hạn như ‘Later’, ‘Cancel’, ‘OK’).

Trong Android, các thông báo mặc định được tắt đi bằng cách click vào bên ngoài hộp thoại thông báo. Việc tắt thông báo sẽ được xử lý bằng một tham số tùy chọn, với một onDismiss callback property { onDismiss: () => {} }. Tuy nhiên, chúng ta có thể vô hiệu hóa property tắt thông báo bằng cách sử dụng property {cancelable: false}.

Ví dụ về React Native Alert

Trong ví dụ này, chúng ta sẽ tạo 2 thông báo trên 2 nút. Một thông báo chứa 2 nút lựa chọn và không có property cancelable. Thông báo còn lại chứa 3 nút lựa chọn và giá trị của property cancelable là false.

App.js

import React, { Component } from 'react';  
import { Alert, AppRegistry, Button, StyleSheet, View } from 'react-native';  
 
export default class ButtonBasics extends Component {  
    showAlert1() {  
        Alert.alert(  
            'Alert Title',  
            'My Alert Msg',  
            [  
                {  
                    text: 'Cancel',  
                    onPress: () => console.log('Cancel Pressed'),  
                    style: 'cancel',  
                },  
                {text: 'OK', onPress: () => console.log('OK Pressed')},  
            ]  
        );  
    }  
    showAlert2() {  
        Alert.alert(  
            'Alert Title',  
            'My Alert Msg',  
            [  
                {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},  
                {  
                    text: 'Cancel',  
                    onPress: () => console.log('Cancel Pressed'),  
                    style: 'cancel',  
                },  
                {text: 'OK', onPress: () => console.log('OK Pressed')},  
            ],  
            {cancelable: false}  
        )  
    }  
    render() {  
        return (  
            <View style={styles.container}>
                <View style={styles.buttonContainer}>
                    <Button
                        onPress={this.showAlert1}
                        title="Button 1"
                    />
                </View>
                <View style={styles.buttonContainer}>
                    <Button
                        onPress={this.showAlert2}
                        title="Button 2"
                        color="#009933"
                    />
                </View>
            </View>
        );  
    }  
}  
 
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        justifyContent: 'center',  
    },  
    buttonContainer: {  
        margin: 20
    },  
    multiButtonContainer: {  
        margin: 20,  
        flexDirection: 'row',  
        justifyContent: 'space-between'
    }  
})

Output:

2. React Native Geolocation

Geolocation API được sử dụng để lấy vị trí địa lý (vĩ độ và kinh độ) của một địa điểm. Nó mở rộng phần vị trí địa lý của web. API này có sẵn trên toàn cầu thông qua navigator.geolocation, vì vậy bạn sẽ không cần phải import nó.

Trong Android, Geolocation API sử dụng android.location API. Tuy nhiên, API không được Google khuyên dùng bởi nó kém chính xác và chậm hơn so với Google Location Services API. Để sử dụng Google Location Services API trong React Native, chúng ta sử dụng module react-native-geolocation-service.

Các tùy chỉnh và Thiết lập của React Native

Trong phần này, chúng ta sẽ thảo luận về các dự án được tạo bởi react-native init, expo init hoặc Create React Native App.

iOS:

Với nền tảng iOS, chúng ta sẽ bao gồm khóa NSLocationWhenInUseUsageDescription vào Info.plist để bật geolocation. Geolocation mặc định được bật khi ứng dụng được tạo bằng react-native init.

Để bật Geolocation chạy ẩn, chúng ta sẽ bao gồm khóa 'NSLocationAlwaysUsageDescription' trong Info.plist. Điều này đòi hỏi phải thêm các vị trí như một chế độ nền trong tab ‘Capabilities’ của Xcode.

Android:

Để truy cập vào vị trí trên Android, chúng ta cần phải thêm <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> vào tệp AndroidManifest.xml.

Android API >=23 đòi hỏi phải yêu cầu quyền ACCESS_FINE_LOCATION sử dụng PermissionsAndroid API.

Các phương thức của Geolocation

Phương thứcMô tả
getCurrentPosition()Kích hoạt success callback một lần với thông tin mới nhất về vị trí.
watchPosition()Kích hoạt success callback khi nào vị trí thay đổi. Nó trả về một watchId (số).
clearWatch()Xóa watchId của watchPosition().
stopObserving()Ngừng quan sát thay đổi vị trí của thiết bị cũng như loại bỏ tất cả các listener đã được đăng ký trước đó.
setRNConfiguration()Đặt các lựa chọn tùy chỉnh, được sử dụng trong tất cả các yêu cầu vị trí.
requestAuthorization()Nó yêu cầu các quyền vị trí thích hợp dựa trên khóa được tùy chỉnh trên pList.

Ví dụ về React Native Geolocation

App.js

import React from 'react';  
import { StyleSheet,Platform, Text, View } from 'react-native';  
 
export default class App extends React.Component {  
    constructor(){  
        super();  
        this.state = {  
            ready: false,  
            where: {lat:null, lng:null},  
            error: null
        }  
    }  
    componentDidMount(){  
        let geoOptions = {  
            enableHighAccuracy:false,  
            timeOut: 20000, //20 second  
          //  maximumAge: 1000 //1 second  
        };  
        this.setState({ready:false, error: null });  
        navigator.geolocation.getCurrentPosition( this.geoSuccess,  
            this.geoFailure,  
            geoOptions);  
    }  
    geoSuccess = (position) => {  
        console.log(position.coords.latitude);  
 
        this.setState({  
            ready:true,  
            where: {lat: position.coords.latitude,lng:position.coords.longitude }  
        })  
    }  
    geoFailure = (err) => {  
        this.setState({error: err.message});  
    }  
    render() {  
        return (  
            <View style={styles.container}>
                { !this.state.ready && (  
                    <Text style={styles.big}>Using Geolocation in React Native.</Text>
                )}
                { this.state.error && (  
                    <Text style={styles.big}>Error: {this.state.error}</Text>
                )}
                { this.state.ready && (  
                    <Text style={styles.big}>
                        Latitude: {this.state.where.lat}
                        Longitude: {this.state.where.lng}
                    </Text>
                )}
            </View>
        );  
    }  
}  
 
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        backgroundColor: '#fff',  
        alignItems: 'center',  
        justifyContent: 'center'
    },  
    big: {  
        fontSize: 25
    }  
});

Output:

3. Liên kết và sử dụng các thư viện bên thứ ba

Thư viện của bên thứ ba cung cấp tính năng cho ứng dụng gốc mà không có trong React Native. Nếu tham khảo trong tài liệu của React Native chúng ta sẽ thấy có rất nhiều chức năng bị thiếu (chẳng hạn như maps).

Do vậy, chúng ta cần phải thêm các thư viện của bên thứ ba vào dự án. Trong phần này, chúng ta sẽ học cách thêm các thư viện từ bên thứ ba vào ứng dụng (thêm các biểu tượng của bên thư ba). Có sẵn rất nhiều bộ các gói biểu tượng. Dưới đây chúng ta có thể kể đến một số:

  • AntDesign
  • Entypo
  • EvilIcons
  • Feather
  • FontAwesome
  • FontAwesome 5
  • Foundation
  • Ionicons
  • MaterialIcons
  • MaterialCommunityIcons
  • Octicons
  • Zocial
  • SimpleLineIcons

Cài đặt các thư viện

Có rất nhiều phương pháp và lệnh để cài đặt các thư viện tùy thuộc vào OS phát triển và OS đích. Chúng ta sẽ cài đặt các thư viện Ionicons. Để cài đặt trên Windows, chúng ta chạy lệnh: $ npm install react-native-vector-icons --save.

Tạo một dự án và chạy 'npm install --save react-native-vector-icons' với đường dẫn D:\ReactNative\navigationApp>npm install –save react-native-vector-icons

Liên kết các thư viện trên Android

Mở tệp android/settings.gradle và thêm vào các dòng code dưới đây. Ở đây, chúng ta chỉ thêm vào thư viện Ionicons. Nếu bạn muốn thêm các thư viện khác, chỉ cần thêm chúng vào thẻ include kèm theo đường dẫn và thư viện trong thư mục android ở project như dưới đây:

  1. include ':react-native-vector-icons'
  2. project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')

Bây giờ, hãy thêm phần phụ thuộc sau vào android/app/build.gradle:

implementation project(':react-native-vector-icons')

Trước đó, cho đến năm 2018, thuật ngữ biên dịch được sử dụng thay thế cho việc triển khai.

Trong, android/app/src/main/java/com/{project_directory}/MainApplication.java

import com.oblador.vectoricons.VectorIconsPackage;  
...  
@Override
  protected List<ReactPackage> getPackages() {  
    return Arrays.<ReactPackage>asList(  
      new MainReactPackage(),  
      new VectorIconsPackage()  
    );  
  }

Để thêm nhiều thư viện hơn, chỉ cần phân tách chúng bằng dấu phẩy và thêm gói thư viện. Các thủ tục trên là phổ biến để thêm thư viện gốc trong Android.

Bây giờ, trong ‘android / app / build.gradle’, hãy thêm phần phụ thuộc sau:

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
project.ext.vectoricons = [  
    iconFontNames: ['Ionicons.ttf'] // Name of the font files you want to copy  
]

Ví dụ về liên kết thư viện bên thứ ba trong React Native

Trong ví dụ này, chúng ta sẽ thêm trash icon của thư viện Ionicons. Mở ứng dụng của bạn và import biểu tượng từ package 'react-native-vector-icons/Ionicons'. Tìm biểu tượng bạn muốn thêm tại trang ionicons.com (ở đây sẽ là ios-trash).

Trong npm doc, Bạn sẽ tìm thấy thành phần Icon và các property của nó.

App.js

import React, {Component} from 'react';  
import {Platform, StyleSheet, Text, View, TouchableOpacity,Alert} from 'react-native';  
import Icon from 'react-native-vector-icons/Ionicons';  
 
type Props = {};  
export default class App extends Component<Props> {  
  deleteItem = ()=>{  
    Alert.alert("delete icon pressed")  
  }  
  render() {  
    return (  
      <View style={styles.container}>
        <Text style={styles.textStyle}>Adding Ionicons library</Text>
        <TouchableOpacity style={styles.touchableStyle} onPress= {this.deleteItem} >
            <Icon size={30} name="ios-trash" color="red"/>
        </TouchableOpacity>
      </View>
    );  
  }  
}  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
  },  
   textStyle:{  
      fontSize:25,  
      marginTop: 30,  
      textAlign: 'center',  
   },  
   touchableStyle:{  
     marginTop: 80,  
     justifyContent: 'center',  
     alignItems: "flex-end",  
     marginRight: 50,  
   }  
}); 

Output:

Phần 3: Điều hướng

1. React Native Navigation

React Native Navigation được sử dụng để quản lý việc trình bày, và chuyển đổi giữa các trang. Có 2 kiểu điều hướng trong các ứng dụng di động. Đó là kiểu điều hướng stack và điều hướng tabbed.

Cài đặt React Navigation

React Navigation được tạo ra bởi cộng đồng React Native để cung cấp giải pháp điều hướng bằng JavaScript.

Tạo một dự án React Native và cài đặt các package và phần phụ thuộc cần thiết.

Cài đặt package react-navigation trong dự án React Native bằng một trong các lệnh sau:

  1. yarn add react-navigation
  2. # or with npm
  3. # npm install --save react-navigation

Sau khi đã thực thi thành công các lệnh trên, nó sẽ thêm "react-navigation": "^3.3.0" (3.3.0 là số phiên bản) trong tệp package.json.

Sau đó, cài đặt package react-native-gesture-handler:

  1. yarn add react-native-gesture-handler
  2. # or with npm
  3. # npm install --save react-native-gesture-handler

Bây giờ, liên kết tất cả các phần phụ thuộc gốc với nhau sử dụng lệnh sau:

react-native link react-native-gesture-handler

Để hoàn thành cài đặt 'react-native-gesture-handler' cho Android, chỉnh sửa như dưới đây trong MainActivity.java:

projectDirectory/android/app/src/main/java/com/project/MainActivity.java

import com.facebook.react.ReactActivityDelegate;  
import com.facebook.react.ReactRootView;  
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;  
 
. . .  
 
@Override
protected ReactActivityDelegate createReactActivityDelegate() {  
    return new ReactActivityDelegate(this, getMainComponentName()) {  
        @Override
        protected ReactRootView createRootView() {  
            return new RNGestureHandlerEnabledRootView(MainActivity.this);  
        }  
    };  
}

Tạo một stack navigator

Để tạo một điều hướng stack, chúng ta import các hàm createStackNavigator và createAppContainer của thư viện react-navigation.

App.js

import React from "react";  
import {Button, View, Text } from "react-native";  
import { createStackNavigator, createAppContainer } from "react-navigation";  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Home Screen</Text>
            </View>
        );  
    }  
}  
 
const AppNavigator = createStackNavigator({  
    Home: {  
        screen: HomeScreen
    }  
});  
export default createAppContainer(AppNavigator);

createStackNavigator là một hàm mà lấy một đối tượng điều chỉnh tuyến (route) và một đối tượng các tùy chọn. Nó trả về một thành phần.

MainActivity.java

package com.naviexe;  
 
import com.facebook.react.ReactActivity;  
import com.facebook.react.ReactActivityDelegate;  
import com.facebook.react.ReactRootView;  
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;  
 
public class MainActivity extends ReactActivity {  
 
    @Override
    protected String getMainComponentName() {  
        return "naviExe";  
    }  
    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {  
        return new ReactActivityDelegate(this, getMainComponentName()) {  
            @Override
            protected ReactRootView createRootView() {  
                return new RNGestureHandlerEnabledRootView(MainActivity.this);  
            }  
        };  
    }  
}

Khi chúng ta chạy code như trên, chúng ta sẽ thấy một thanh điều hướng trống chứa thành phần HomeScreen.

Output:

Tùy chỉnh tuyến tốc ký

Chúng ta chỉ có một trang đơn là một tuyến duy nhất, đó là thành phần Home, chúng ta không cần phải dùng {screen: HomeScreen} , có thể trực tiếp sử dụng thành phần home.

const AppNavigator = createStackNavigator({  
    Home: HomeScreen
});

Thêm tiêu đề và kiểu cho điều hướng

static navigationOptions = {  
    title: 'Home',  
    headerStyle: {  
        backgroundColor: '#f4511e',  
    },  
    headerTintColor: '#0ff',  
    headerTitleStyle: {  
       fontWeight: 'bold',  
    },  
};  
import React from 'react';  
import { View, Text } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Home',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
      //  headerTintColor: '#0ff',  
        headerTitleStyle: {  
           fontWeight: 'bold',  
        },  
    };  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        );  
    }  
}  
const AppNavigator = createStackNavigator({  
    Home: HomeScreen
});  
 
export default createAppContainer(AppNavigator);

Thêm một trang tuyến (route screen) thứ hai

Tạo một lớp khác (ProfileScreen) trong tệp App.js để thêm trang tuyến thứ hai vào stack navigator.

class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Details Screen</Text>
            </View>
        );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);

Đối tượng tùy chọn initialRouteName xác định cụ thể tuyến ban đầu của điều hướng stack.

Code hoàn chỉnh:

App.js

import React from 'react';  
import { View, Text } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Details Screen</Text>
            </View>
        );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
export default createAppContainer(AppNavigator);

Output:

Trong phần tiếp theo, chúng ta sẽ học cách để đi từ tuyến Home đến tuyến Profile (từ trang này sang trang khác).

2. Tùy chỉnh thanh tiêu đề

Property tĩnh của một thành phần screen được gọi là navaigationOptions. Nó có thể là một đối tượng hoặc một hàm. Nó trả về một đối tượng chứa một vài lựa chọn tùy chỉnh.

Các props của thanh tiêu đề

PropsMô tả
titleĐặt tiêu đề của trang hoạt động.
headerStyleThêm kiểu vào trang tiêu đề.
backgroundColorĐặt màu nền của thanh tiêu đề.
headerTintColorĐặt màu của dòng tiêu đề.
headerTitleStyleThêm kiểu cho dòng tiêu đề.
fontWeightĐặt kiểu font cho dòng tiêu đề.
static navigationOptions = {  
    title: 'HeaderTitle',  
    headerStyle: {  
        backgroundColor: '#f4511e',  
    },  
    headerTintColor: '#0ff',  
    headerTitleStyle: {  
       fontWeight: 'bold',  
    },  
};

Chuyển từ trang này sang trang khác trong React Native Ví dụ 1

Trong ví dụ này, Chúng ta tạo 2 trang là 'Home''Profile'. Trang Home được đặt là trang đầu tiên sử dụng "initialRouteName" property và trang Profile là trang thứ hai.

App.js

import React from 'react';  
import { View, Text, Button } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Home',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
        //headerTintColor: '#0ff',  
        headerTitleStyle: {  
            fontWeight: 'bold',  
        },  
    };  
 
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Profile"
                    onPress={() => this.props.navigation.push('Profile')}
                />
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Profile',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
        headerTintColor: '#0ff',  
        headerTitleStyle: {  
            fontWeight: 'bold',  
        },  
    };  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
                <Button
                    title="Go to Profile... again"
                    onPress={() => this.props.navigation.push('Profile')}
                />
                <Button
                    title="Go to Home"
                    onPress={() => this.props.navigation.navigate('Home')}
                 />
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                />
            </View>
    );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
const AppContainer = createAppContainer(AppNavigator);  
export default class App extends React.Component {  
    render() {  
        return <AppContainer />;  
    }  
}

Output:

Sử dụng các param trong tiêu đề

Để sử dụng các params (tham số) như một dòng tiêu đề, chúng ta cần phải làm cho hàm navigationOptions trả về một đối tượng tùy chỉnh bằng cách sử dụng this.props trong navigationOptions. Bởi nó là property tĩnh của thành phần, "this" ở đây không phải là một phiên bản của thành phần và do đó nó sẽ không có prop nào

Biến navigationOptions thành một hàm trả về một đối tượng chứa {navigation, navigationOptions, screenProps}. navigation là một đối tượng được truyền đến screen props đó là this.props.navigation. Chúng ta cúng có thể lấy các tham số từ điều hướng sử dụng navigation.getParam hay navigation.state.params.

class ProfileScreen extends React.Component {  
    static navigationOptions = ({ navigation }) => {  
        return {  
            title: navigation.getParam('otherParam', 'A Param Header'),  
        };  
    };  
}

Tùy chỉnh navigationOtions của trang hoạt động cũng có thể được cập nhật từ chính thành phần trang hiện tại.

//inside render  
<Button
    title="Update the title"
    onPress={() => this.props.navigation.setParams({otherParam: 'Header Updated!'})}
/>

Code hoàn chỉnh

Trong ví dụ này, chúng ta tạo 2 trang "Home""Profile". Trang Profile đặt dòng tiêu đề của nó bằng: title: navigation.getParam('otherParam', 'A Param Header')

App.js

import React from 'react';  
import { View, Text, Button } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Home',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
        //headerTintColor: '#0ff',  
        headerTitleStyle: {  
            fontWeight: 'bold',  
        },  
    };  
 
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Profile"
                    onPress={() => this.props.navigation.push('Profile')}
                />
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    static navigationOptions = ({ navigation }) => {  
        return {  
            title: navigation.getParam('otherParam', 'A Param Header'),  
        };  
    };  
 
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                />
                <Button
                    title="Update the title"
                    onPress={() => this.props.navigation.setParams({otherParam: 'Header Updated!'})}
                />
            </View>
    );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
const AppContainer = createAppContainer(AppNavigator);  
export default class App extends React.Component {  
    render() {  
        return <AppContainer />;  
    }  
}

Output:

3. Di chuyển giữa các trang

Trong phần này, chúng ta sẽ cùng thảo luận cách di chuyển từ một trang tuyến này sang một trang tuyến khác và quay lại tuyến đầu tiên. Trong phần trước của phần Điều hướng, chúng ta đã tạo stack navigator với 2 trang tuyến (route screen) là Home và Profile.

Chúng ta thực hiện chuyển từ trang này sang trang khác bằng navigation prop, mà sẽ truyền các thành phần screen của chúng ta. Điều này tương tự như viết các dòng code sau cho một trình duyệt web:

<a href="profiles.html">Go to Profile</a>

Cách khác để viết điều này sẽ là

<a href="profiles.html">Go to Profile</a>  
The other way to write this would be:
<a onClick={() => { document.location.href = "profile.html"; }}>Go to Profile</a>

Điều hướng sang trang mới

Có thể điều hướng từ trang này sang trang khác bằng những cách khác nhau:

1.  <Button
2.            title="Go to URL"
3.            onPress={() => this.props.navigation.navigate('url')}  
4.          />

App.js

import React from 'react';  
import { View, Text, Button } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Profile"
                    onPress={() => this.props.navigation.navigate('Profile')}
                />
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
            </View>
    );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
const AppContainer = createAppContainer(AppNavigator);  
export default class App extends React.Component {  
    render() {  
        return <AppContainer />;  
    }  
}

Thêm một thành phần Button trong 'HomeScreen' và thực hiện một hành động onPress{} để gọi hàm this.props.navigation.navigate('Profile'). Click vào thành phần Button sẽ di chuyển trang đến layout ‘ProfileScreen’.

import React from 'react';  
import { View, Text, Button } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Profile"
                    onPress={() => this.props.navigation.navigate('Profile')}
                />
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
            </View>
    );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
const AppContainer = createAppContainer(AppNavigator);  
export default class App extends React.Component {  
    render() {  
        return <AppContainer />;  
    }  
}

Output:

  • this.props.navigation: navigation prop được truyền với tất cả các thành phần screen trong điều hướng stack.
  • navigate(‘Profile’): Gọi hàm navigate với tên tuyến mà chúng ta muốn chuyển đến.

Điều hướng đến một trang tuyến nhiều lần

Thêm điều hướng 'ProfileScreen' đến 'Profile' URL sẽ không thay đổi gì bởi chúng ta đã ở tuyến Profile.

class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
                   <Button
                     title="Go to Profile"
                     onPress={() => this.props.navigation.navigate('Profile')}
                   />
             </View>
    );  
    }  
} 

Để gọi trang Profiles, chủ yếu là trong trường hợp truyền các dữ liệu độc nhất (các tham số) đến mỗi tuyến. Để thực hiện, chúng ta sẽ truyền điều hướng đến push. Phương thức Navigate push biểu thị ý định thêm một tuyến bất kể lịch sử điều hướng hiện tại.

<Button
        title="Go to Profile"
         onPress={() => this.props.navigation.push('Profile')}
/>

Khi nhấn nút chúng ta sẽ gọi phương thức push mỗi lần và thêm một tuyến mới vào stack điều hướng.

Quay lại

Tiêu đề của stack navigator tự động có một nút quay lại khi có thể quay lại từ trang hiện tại. Điều hướng stack của trang đơn sẽ không có nút quay lại bởi sẽ không có gì để chúng ta có thể quay lại.

Đôi khi, chúng ta sẽ phải lập trình để thiếp lập hành vi quay lại, chúng ta sẽ gọi đây là hàm this.props.navigation.goBack();.

App.js

import React from 'react';  
import { View, Text, Button } from 'react-native';  
import { createStackNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Profile"
                    onPress={() => this.props.navigation.push('Profile')}
                />
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text>Profile Screen</Text>
                <Button
                    title="Go to Profile... again"
                    onPress={() => this.props.navigation.push('Profile')}
                />
                <Button
                    title="Go to Home"
                    onPress={() => this.props.navigation.navigate('Home')}
                 />
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                />
            </View>
    );  
    }  
}  
 
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
 
const AppContainer = createAppContainer(AppNavigator);  
export default class App extends React.Component {  
    render() {  
        return <AppContainer />;  
    }  
}

Output:

4. Truyền giá trị giữa các trang

Khi tạo một ứng dụng nhiều trang thì đôi khi yêu cầu cần phải truyền giá trị giữa trang này và trang khác. Chúng ta có thể thực hiện điều này sử dụng hàm this.props.navigation.navigate().

Hàm này được sử dụng để điều hướng giữa các trang khác nhau.

Trước khi đi vào ví dụ, bạn cần phải đọc qua phần React Native Navigation.

Trong ví dụ này, chúng ta sẽ nhập giá trị vào trang đầu tiên và đưa nó vào trang thứ hai.

Giá trị (tham số) được truyền như một đối tượng trong trang thứ nhất đến hàm navigation.navigate:

this.props.navigation.navigate('RouteName', { /* params go here */ })

Cùng một giá trị (tham số) được đọc trong trang thứ hai như sau:

this.props.navigation.getParam(paramName, defaultValue)

Tạo một tệp HomeScreen.js và thêm một thành phần TextInput để nhập giá trị và một Button để gửi. Thành phần TextInput có một onChangeText prop mà cần một hàm để gọi mỗi khi văn bản thay đổi.

HomeScreen.js

import React from 'react';  
//import react in our code.  
import { StyleSheet, View, Button, TextInput } from 'react-native';  
 
export default class HomeScreen extends React.Component {  
 
    constructor(props) {  
        //constructor to set default state  
        super(props);  
        this.state = {  
            username: '',  
        };  
    }  
    static navigationOptions = {  
        title: 'Home',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
        //headerTintColor: '#0ff',  
        headerTitleStyle: {  
            fontWeight: 'bold',  
        },  
    };  
 
    render() {  
        const { navigate } = this.props.navigation;  
        return (  
            //View to hold our multiple components  
            <View style={styles.container}>
            {/*Input to get the value from the user*/}
            <TextInput
        value={this.state.username}
        onChangeText={username => this.setState({ username })}
        placeholder={'Enter Any value'}
        style={styles.textInput}
        />
        <View style={styles.buttonStyle}>
            <Button
        title="Submit"
        // color="#00B0FF"  
        onPress={() =>
        this.props.navigation.navigate('Profile', {  
            userName: this.state.username,  
            otherParam: '101',  
        })  
    }
        />
        </View>
        </View>
    );  
    }  
}  
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        backgroundColor: '#fff',  
        alignItems: 'center',  
        padding: 16,  
    },  
    textInput: {  
        height: 45,width: "95%",borderColor: "gray",borderWidth: 1,fontSize:20,  
    },  
    buttonStyle:{  
        width: "93%",  
        marginTop: 50,  
        backgroundColor: "red",  
    }  
});

Trong code trên userName: this.state.username, trữ giá trị nhập vào thành phần TextInput và otherParam: '101' trực tiếp chỉ định một giá trị. Khi click vào nút, userName và otherParam được truyền đến trang Profile.

ProfileScreen.js

Trong trang này, chúng ta nhân giá trị của userName và otherParam sử dụng navigation.getParam('paramValue', default value) và lần lượt lưu trữ vào đối tượng user_nameother_param. Giá trị của đối tượng JavaScript được chuyển đổi sang chuỗi sử dụng hàm JSON.stringify(object).

import React from 'react';  
import { StyleSheet, View, Text, Button } from 'react-native';  
 
export default class ProfileScreen extends React.Component {  
    static navigationOptions = {  
        title: 'Profile',  
        headerStyle: {  
            backgroundColor: '#f4511e',  
        },  
        //headerTintColor: '#0ff',  
        headerTitleStyle: {  
            fontWeight: 'bold',  
        },  
    };  
    render() {  
        {/*Using the navigation prop we can get the
              value passed from the previous screen*/}  
        const { navigation } = this.props;  
        const user_name = navigation.getParam('userName', 'NO-User');  
        const other_param = navigation.getParam('otherParam', 'some default value');  
        return (  
            <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
                <Text style={{ marginTop: 16,fontSize: 20,}}>
                    This is Profile Screen and we receive value from Home Screen  
                </Text>
                <Text style={styles.textStyle}>User Name: {JSON.stringify(user_name)}</Text>
                <Text style={styles.textStyle}>Other Param: {JSON.stringify(other_param)}</Text>
                <View style={styles.buttonStyle}>
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                />
                </View>
            </View>
        );  
    }  
}  
const styles = StyleSheet.create({  
    textStyle: {  
        fontSize: 23,  
        textAlign: 'center',  
        color: '#f00',  
    },  
 
    buttonStyle:{  
        width: "93%",  
        marginTop: 50,  
        backgroundColor: "red",  
    }  
});

Tạo tệp App.js là điểm bắt đầu của ứng dụng và import HomeScreen và ProfileScreen. HomeScreen được đặt là trang đầu tiên sử dụng initialRouteName.

import React from 'react';  
import {createStackNavigator,createAppContainer} from 'react-navigation';  
import HomeScreen from './HomeScreen';  
import ProfileScreen from './ProfileScreen';  
const AppNavigator = createStackNavigator(  
    {  
        Home: HomeScreen,  
        Profile: ProfileScreen
    },  
    {  
        initialRouteName: "Home"
    }  
);  
export default createAppContainer(AppNavigator);

Output:

Chúng ta cũng gửi và nhận các tham số thành JSON chẳng hạn như:

HomeScreen.js

onPress={() =>  
    navigate('Profile', {  
        JSON_ListView_Clicked_Item: this.state.username,  
    })  
}

ProfileScreen.js

Trong này đọc giá trị theo 2 cách mà không kiểm tra.

{this.props.navigation.state.params.JSON_ListView_Clicked_Item}

Hoặc kiểm tra giá trị nhập vào có phải là rỗng (null) hay không

{this.props.navigation.state.params.JSON_ListView_Clicked_Item
    ? this.props.navigation.state.params.JSON_ListView_Clicked_Item
     : 'No Value Passed'}  
 <Text style={styles.textStyle}>
         {this.props.navigation.state.params.JSON_ListView_Clicked_Item}
     </Text>
 <Text style={{ marginTop: 16,fontSize: 20, }}>With Check</Text>
     {/*If you want to check the value is passed or not,
             you can use conditional operator.*/}  
 <Text style={styles.textStyle}>
     {this.props.navigation.state.params.JSON_ListView_Clicked_Item
         ? this.props.navigation.state.params.JSON_ListView_Clicked_Item
         : 'No Value Passed'}

Output:

5. Điều hướng Tab

Điều hướng Tab là kiểu điều hướng phổ biến nhất trong các ứng dụng di động. Điều hướng Tab được gắn ở cuối trang hoặc ở đầu trang bên dưới phần tiêu đề hoặc đôi khi chính là phần tiêu đề. Nó được sử dụng để chuyển qua lại giữa các trang tuyến.

Để tạo điều hướng Tab, trước tiên chúng ta import createBottomTabNavigatorcreateAppContainer và trong các hàm gốc của thư viện react-navigation.

Tùy chỉnh Bottom Tab Navigator

Có nhiều prop có thể tùy chỉnh được của BottomTabNavigator. Một trong số đó có thể kể đến:

PropMô tả
initialRouteNameĐịnh nghĩa tuyến tab đầu tiên khi ứng dụng khởi động.
orderLà một mảng của trang tuyến, dùng để sắp xếp thứ tự của các tab.
pathsCung cấp sơ đồ của các trang tuyến đến path config mà sẽ ghi đè lên các đường dẫn được đặt trong routeConfigs.
lazyĐặt là {true} thì sẽ render tab khi tab hoạt động lần đầu. Nếu đặt là false, tất cả các tab đều được render ngay lập tức. Giá trị mặc định là true.
tabBarComponentNó đè lên các thành phần, được sử dụng làm thanh tab. Không bắt buộc phải sử dụng.
tabBarOptionsLà một đối tượng của các property sau: activeTintColor, activeBackgroundColor, inactiveTintColor , inactiveBackgroundColor, showLabel, showIcon, style, labelStyle, tabStyle, allowFontScaling.

Ví dụ về điều hướng Tab

Tạo 2 lớp tên là HomeScreen và ProfileScreen. Đăng kí các lớp này trong hàm createBottomTabNavigator function lần lượt với Home và Profile tab.

import React from 'react';  
import { StyleSheet, Text, View } from 'react-native';  
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';  
 
class HomeScreen extends React.Component {  
    render() {  
        return (  
            <View style={styles.container}>
                <Text>Home Screen</Text>
            </View>
        );  
    }  
}  
class ProfileScreen extends React.Component {  
    render() {  
        return (  
            <View style={styles.container}>
                <Text>Profile Screen</Text>
            </View>
        );  
    }  
}  
 
const TabNavigator = createBottomTabNavigator({  
    Home: HomeScreen,  
    Profile: ProfileScreen,  
});  
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        justifyContent: 'center',  
        alignItems: 'center'
    },  
});  
 
export default createAppContainer(TabNavigator);

Output:

Nếu chúng ta đặt initialRouteName: "Profile" thì nó sẽ tải "ProfileScreen" là tuyến tab ban đầu.

const TabNavigator = createBottomTabNavigator({  
    Home: HomeScreen,  
    Profile: ProfileScreen,  
},  
{  
    initialRouteName: "Profile"
}  
);

Thêm biểu tượng vào bên dưới điều hướng Tab

Trong phần này, chúng ta sẽ thêm các biểu tượng vào bên dưới điều hướng Tab. Trước khi đi vào phần này, hãy đọc lại phần Điều hướng Tab để biết cách cài đặt Điều hướng Tab cuối trang.

Ví dụ:

Đầu tiên, thêm các thư viện và phần phụ thuộc cần thiết vào dự án React Native:

  1. Thêm thư viện react navigation với lệnh sau: yarn add react-navigation
  2. Thêm thư viện react native gesture handler với lệnh sau: yarn add react-native-gesture-handler
  3. Thêm thư viện react native vector icons với lệnh sau: yarn add react-native-vector-icons

Sau khi đã thực thi thành công các lệnh trên, liên kết các thư viện này đến dự án react native với lệnh sau: react-native link

Lệnh trên hãy thêm các phần phụ thuộc dưới đây vào tệp D:\your_directory\your_reactNativeProject\package.json file.

  1. "react-native-gesture-handler": "^1.1.0",
  2. "react-native-vector-icons": "^6.3.0",
  3. "react-navigation": "^3.3.2"

D:\your_directory\your_reactNativeProject\android\app\build.gragle

  1. implementation project(':react-native-vector-icons')
  2. implementation project(':react-native-gesture-handler')

D:\your_directory\your_reactNativeProject\android\settings.gradle file:

include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '..\node_modules\react-native-vector-icons\android')  
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '..\node_modules\react-native-gesture-handler\android')

Thực hiện một chút thay đổi (thay thế ‘\’ bằng ‘/’) trong cấu trúc tuyến đường ở trên như:

include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')  
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')

D:\your_directory\your_reactNativeProject\android\app\src\main\java\com\ reactNativeProject\MainApplication.java

import com.oblador.vectoricons.VectorIconsPackage;  
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;  
. . .  
protected List<ReactPackage> getPackages() {  
  return Arrays.<ReactPackage>asList(  
      new MainReactPackage(),  
        new VectorIconsPackage(),  
        new RNGestureHandlerPackage()  
  );  
}

App.js

Tạo 2 lớp "HomeScreen""ProfileScreen" lần lượt cho 2 tab "Home""Profile". Hàm createBottomTabNavigator tạo một thanh tab bên dưới trang để bạn có thể chuyển qua lại giữa các tuyến khác nhau.

Đặt "HomeScreen" vào tiêu đề "Home""ProfileScreen" vào tiêu đề "Profile". Thẻ Icon thêm các biểu tượng vào điều hướng tab. Chúng ta có thể sử dụng các tên biểu tượng khác nhau trên ionicons.com

import React from 'react';  
import {StyleSheet, Text, View} from 'react-native';  
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';  
import Icon from 'react-native-vector-icons/Ionicons';  
class HomeScreen extends React.Component {  
  render() {  
    return (  
        <View style={styles.container}>
          <Text>Home Screen</Text>
        </View>
    );  
  }  
}  
class ProfileScreen extends React.Component {  
  render() {  
    return (  
        <View style={styles.container}>
          <Text>Profile Screen</Text>
        </View>
    );  
  }  
}  
 
const TabNavigator = createBottomTabNavigator(  
    {  
      Home:{  
        screen:HomeScreen,  
        navigationOptions:{  
          tabBarLabel:'Home',  
          tabBarIcon:({tintColor})=>(  
              <Icon name="ios-home" color={tintColor} size={25}/>
          )  
        }  
      },  
      Profile: {  
        screen:ProfileScreen,  
        navigationOptions:{  
          tabBarLabel:'Profile',  
          tabBarIcon:({tintColor})=>(  
              <Icon name="ios-person" color={tintColor} size={25}/>
          )  
        }  
      },  
    },  
    {  
      initialRouteName: "Home"
    },  
);  
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center'
  },  
});  
 
export default createAppContainer(TabNavigator);

Output:

6. Tạo Material Bottom Tab Navigator

Kiểu vật liệu (material style) cung cấp thêm hiệu ứng thiết kế cho thanh tab ở phía dưới màn hình. Các thiết kế sẽ khiến bạn chú ý đến các tab phía bên dưới hơn. Các thành phần của trang tab sẽ không được đặt lên cho đến khi các trang được tập trung vào lần đầu.

Để sử dụng material design navigator, cài đặt thư viện react-navigation-material-bottom-tabs như sau:

npm install react-navigation-material-bottom-tabs react-native-paper

Thư viện này sử dụng thành phần BottomNavigation từ react-native-paper. Nó cũng yêu cầu cần phải cài react-native-vector-icons.

createMaterialBottomTabNavigator(RouteConfigs, MaterialBottomTabNavigatorConfig);

Trong ví dụ này, chúng ta sẽ cài đặt material bottom tab navigator để làm nổi bật biểu tượng của tab đang hoạt động và tiêu đề của nó. Các tab còn lại sẽ chỉ hiển thị biểu tượng mà không có tiêu đề. Để sử dụng các các thiết kế vật liệu, import hàm createMaterialBottomTabNavigator từ thư viện react-navigation-material-bottom-tabs.

App.js

import React from 'react';  
import {StyleSheet, Text, View,Button} from 'react-native';  
import { createBottomTabNavigator, createAppContainer} from 'react-navigation';  
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';  
import Icon from 'react-native-vector-icons/Ionicons';  
class HomeScreen extends React.Component {  
  render() {  
    return (  
        <View style={styles.container}>
          <Text>Home Screen</Text>
        </View>
    );  
  }  
}  
class ProfileScreen extends React.Component {  
  render() {  
    return (  
        <View style={styles.container}>
          <Text>Profile Screen</Text>
        </View>
    );  
  }  
}  
class ImageScreen extends React.Component {  
    render() {  
        return (  
            <View style={styles.container}>
                <Text>Image Screen</Text>
            </View>
        );  
    }  
}  
class CartScreen extends React.Component {  
    render() {  
        return (  
            <View style={styles.container}>
                <Text>Cart Screen</Text>
            </View>
        );  
    }  
}  
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        justifyContent: 'center',  
        alignItems: 'center'
    },  
});  
const TabNavigator = createMaterialBottomTabNavigator(  
    {  
        Home: { screen: HomeScreen,  
            navigationOptions:{  
                tabBarLabel:'Home',  
                tabBarIcon: ({ tintColor }) => (  
                    <View>
                        <Icon style={[{color: tintColor}]} size={25} name={'ios-home'}/>
                    </View>),  
            }  
        },  
        Profile: { screen: ProfileScreen,  
            navigationOptions:{  
                tabBarLabel:'Profile',  
                tabBarIcon: ({ tintColor }) => (  
                    <View>
                        <Icon style={[{color: tintColor}]} size={25} name={'ios-person'}/>
                    </View>),  
                activeColor: '#f60c0d',  
                inactiveColor: '#f65a22',  
                barStyle: { backgroundColor: '#f69b31' },  
            }  
        },  
        Image: { screen: ImageScreen,  
            navigationOptions:{  
                tabBarLabel:'History',  
                tabBarIcon: ({ tintColor }) => (  
                    <View>
                        <Icon style={[{color: tintColor}]} size={25} name={'ios-images'}/>
                    </View>),  
                activeColor: '#615af6',  
                inactiveColor: '#46f6d7',  
                barStyle: { backgroundColor: '#67baf6' },  
            }  
        },  
        Cart: {  
            screen: CartScreen,  
            navigationOptions:{  
                tabBarLabel:'Cart',  
                tabBarIcon: ({ tintColor }) => (  
                    <View>
                        <Icon style={[{color: tintColor}]} size={25} name={'ios-cart'}/>
                    </View>),  
            }  
        },  
    },  
    {  
      initialRouteName: "Home",  
      activeColor: '#f0edf6',  
      inactiveColor: '#226557',  
      barStyle: { backgroundColor: '#3BAD87' },  
    },  
);  
 
export default createAppContainer(TabNavigator);

Output:

7. React Native Top Tab Navigator (createMaterialTopTabNavigator)

Kiểu vật liệu createMaterialTopTabNavigator dược dùng để tạo tab navigator ở trên đầu trang. Nó cung cấp chức năng tạo và hiển thị nhiều bộ định tuyến trang. Các trang này đươc chuyển qua lại lẫn nhau bằng cách gõ nhẹ vào tuyến hoặc vuốt theo chiều ngang. Các thành phần tab screen sẽ được đặt lên khi chúng được tập trung vào.

Hàm createMaterialTopTabNavigator của thư viện react-navigation giúp chúng ta sễ dàng cài đặt top tab navigator:

createMaterialTopTabNavigator(RouteConfigs, TabNavigatorConfig);

Ví dụ

Hãy tạo một top tab navigator với thanh trạng thái và phần tiêu đề tùy chọn. Trong ví dụ này, Chúng ta sẽ tạo 3 trang khác nhau cho các bộ định tuyến "Home", "Profile""Settings" . Mỗi trang định tuyến sẽ được tạo trong các tệp riêng.

Cấu trúc thư mục của ứng dụng

Tạo một thư mục src trong dự án tuyến của bạn. Bên trong thư mục src tạo một tệp index.js và 2 thư mục khác là lib và screens. Trong thư mục screens, chúng ra sẽ đặt 3 tệp của trang đó là index.js (HomeScreen), profile.js (ProfileScreen), và settings.js (SettingsScreen). Trong thư mục lib, chúng ta cài đặt createMaterialTopTabNavigator để tạo top tab navigator.

topNavigation/index.js

Thay đổi một chút trong tệp topNavigation/index.js (thay './App' bằng './src').

import {AppRegistry} from 'react-native';
import App from './src';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

Tạo 3 lớp và import Icon từ package 'react-native-vector-icons/Ionicons'. Cài đặt tabBarIcon và thêm thẻ Icon vào nó.

src/screens/index.js

import React, {Component} from 'react';
import {View,Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
export default class HomeScreen extends Component{
render() {
return(
<View>
<Text>This is Home Screen</Text>
</View>
)
}
}
HomeScreen.navigationOptions={
tabBarIcon:({tintColor, focused})=>(
<Icon
name={focused ? 'ios-home' : 'md-home'}
color={tintColor}
size={25}
/>
)
}

src/screens/profile.js

import React, {Component} from 'react';
import {View,Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
export default class ProfileScreen extends Component{
render(){
return(
<View>
<Text>this is profile screen</Text>
</View>
)
}
}
ProfileScreen.navigationOptions={
tabBarIcon:({tintColor, focused})=>(
<Icon
name={focused ? 'ios-person' : 'md-person'}
color={tintColor}
size={25}
/>
)
}

src/screens/settings.js

import React, {Component} from 'react';
import {View,Text} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
export default class SettingScreen extends Component{
render(){
return(
<View>
<Text>this is setting screen</Text>
</View>
)
}
}
SettingScreen.navigationOptions={
tabBarIcon:({tintColor, focused})=>(
<Icon
name={focused ? 'ios-settings' : 'md-settings'}
color={tintColor}
size={25}
/>
)
}

src/lib/router.js

Trong tệp router.js, import các hàm createMaterialTopTabNavigatorcreateAppContainer của thư viện ‘react-navigation’. Import tất cả các lớp định tuyến trong nó và đặt chúng theo trình tự mà chúng ta muốn hiển thị trên đầu tab navigator.

  • activeTintColor: đặt màu đề cập cho bộ định tuyến đang hoạt động.
  • showIcon: hiển thị {true} và ẩn {false} biểu tượng bộ định tuyến.
  • showLabel: hiển thị {true} và ẩn {false} tiêu đề của bộ định tuyến. Theo mặc định, nó là true.
import React from 'react';
import {createMaterialTopTabNavigator,createAppContainer} from 'react-navigation';
import HomeScreen from "../screens/index";
import ProfileScreen from "../screens/profile";
import SettingScreen from "../screens/settings";

const AppNavigator = createMaterialTopTabNavigator(
{
Home: HomeScreen,
Profile: ProfileScreen,
Settings: SettingScreen,
},
{
tabBarOptions: {
activeTintColor: 'white',
showIcon: true,
showLabel:false,
style: {
backgroundColor:'red'
}
},
}
)
export default createAppContainer(AppNavigator);

src/index.js

Import AppNavigator từ './lib/router' và chỉ định AppNavigator vào một hằng số AppIndex trong tệp này. Tùy biến thanh trạng thái sử dụng thẻ StatusBar và thêm phần tiêu đề vào trên đầu của tab navigator.

import React, {Component} from 'react';
import {StyleSheet, Text, View,StatusBar} from 'react-native';
import {createAppContainer} from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons';

import AppNavigator from './lib/router';
const AppIndex = createAppContainer(AppNavigator)

export default class App extends Component{
render(){
return(
<View style={{flex:1}} >
<StatusBar
backgroundColor='red'
barStyle='light-content'
/>
<View style={styles.header}>
<Icon name='ios-camera' size={28} color='white'/>
<Icon name='ios-menu' size={28} color='white'/>
</View>
<AppIndex/>
</View>
)
}
}
const styles = StyleSheet.create({
wrapper: {
flex: 1,
},
header:{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: 'red',
paddingHorizontal: 18,
paddingTop: 5,
}
});

Output:

8. Điều hướng Ngăn kéo (createDrawerNavigator)

React Native Drawer Navigation là một bảng UI hiển thị menu điều hướng của ứng dụng. Khi không sử dụng thì nó mặc định sẽ được ẩn đi, nó sẽ hiện ra khi người dùng vuốt ngón tay từ cạnh trang hay khi người dùng chạm vào biểu tượng ngăn kéo trên thanh ứng dụng.

React Native Drawer Navigation import createDrawerNavigator từ thư viện react-navigation:

import { createDrawerNavigator } from 'react-navigation'

Cài đặt createDrawerNavigator() để thêm danh sách các lớp (trang):

createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig);

Để đóng và mở các ngăn kéo, sử dụng các phương thức helper:

this.props.navigation.openDrawer();
this.props.navigation.closeDrawer();

Nếu bạn muốn bật/tắt ngăn kéo thì có thể gọi phương thức sau:

this.props.navigation.toggleDrawer();

Mỗi một phương thức openDrawer(), closeDrawer(), và toggleDrawer() đơn giản là các hành động truyền đi như:

this.props.navigation.dispatch(DrawerActions.openDrawer());  
this.props.navigation.dispatch(DrawerActions.closeDrawer());  
this.props.navigation.dispatch(DrawerActions.toggleDrawer());

Ví dụ: Tạo 2 lớp riêng biệt "DashboardScreen""WelcomeScreen" trong ứng dụng react native để hiển thị trên trang. Thêm các trang này vào createStackNavigator và thêm biểu tượng "md-menu" của package 'react-native-vector-icons/Ionicons'. Khi nhấn vào biểu tượng menu, gọi phương thức navigation.openDrawer() để mở ngăn kéo.

Bây giờ, hãy import createDrawerNavigator từ package 'react-navigation' và cài đặt createDrawerNavigator(). Sau đó hãy thêm trang điều hướng stack lên trên nó.

import React, { Component } from 'react';  
import { View, Text, StyleSheet, Button } from 'react-native';  
import Icon from 'react-native-vector-icons/Ionicons';  
 
import {  
    createSwitchNavigator,  
    createAppContainer,  
    createDrawerNavigator,  
    createStackNavigator
} from 'react-navigation';  
export default class App extends Component {  
    render() {  
        return <AppContainer />;  
    }  
}  
 
class WelcomeScreen extends Component {  
    static navigationOptions = {  
         title: 'Welcome',  
    };  
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>WelcomeScreen</Text>
                <Button
                    title="Go to DashboardScreen"
                    onPress={() => this.props.navigation.navigate('Dashboard')}
                />
            </View>
        );  
    }  
}  
 
class DashboardScreen extends Component {  
    static navigationOptions = {  
         title: 'Dashboard',  
    };  
 
    render() {  
        return (  
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>DashboardScreen</Text>
            </View>
        );  
    }  
}  
const DashboardStackNavigator = createStackNavigator(  
    {  
        DashboardNavigator: DashboardScreen
    },  
    {  
        defaultNavigationOptions: ({ navigation }) => {  
        return {  
            headerLeft: (  
                <Icon
                    style={{ paddingLeft: 10 }}
                    onPress={() => navigation.openDrawer()}
                    name="md-menu"
                    size={30}
                />
            )  
        };  
        }  
    }  
);  
 
const WelcomeStackNavigator = createStackNavigator(  
    {  
        WelcomeNavigator: WelcomeScreen
    },  
    {  
        defaultNavigationOptions: ({ navigation }) => {  
            return {  
                headerLeft: (  
                    <Icon
                        style={{ paddingLeft: 10 }}
                        onPress={() => navigation.openDrawer()}
                        name="md-menu"
                        size={30}
                    />
                )  
            };  
        }  
    }  
);  
const AppDrawerNavigator = createDrawerNavigator({  
    Dashboard: {  
        screen: DashboardStackNavigator
    },  
    Welcome: {  
        screen: WelcomeStackNavigator
    },  
});  
 
const AppSwitchNavigator = createSwitchNavigator({  
    Dashboard: { screen: AppDrawerNavigator },  
    Welcome: { screen: WelcomeScreen },  
 
});  
 
const AppContainer = createAppContainer(AppSwitchNavigator);  
 
const styles = StyleSheet.create({  
    container: {  
        flex: 1,  
        alignItems: 'center',  
        justifyContent: 'center'
    }  
});

Output:

Phần 4: Storage

1. React Native AsyncStorage

React Native AsyncStorage là một hệ thống lưu trữ đơn giản, không mã hóa, không đối xứng và liên tục, để lưu trữ dữ liệu trên toàn ứng dụng Nó lưu trữ dữ liệu dưới dạng cặp khóa-giá trị.

React Native khuyến khích sử dụng các trừu tượng ngoài AsyncStorage thay vì trực tiếp dùng AsyncStorage bởi nó hoạt động trên toàn ứng dụng.

Trên iOS, AsyncStorage được chấp nhận bởi code gốc. Code gốc của iOS lưu trữ các giá trị nhỏ trong một từ điển được tuần tự hóa và các giá trị lớn trong các tệp riêng.

Trong Android, AsyncStorage sẽ sử dụng SQLite hoặc RocksDB nếu có sẵn.

Để sử dụng AsyncStorage, import thư viện AsyncStorage như sau:

import {AsyncStorage} from 'react-native';

Duy trì dữ liệu (persist data)

React Native AsyncStorage lưu trữ dữ liệu sử dụng phương thức setItem() như sau:

AsyncStorage.setItem('key', 'value');

Ví dụ duy trì một giá trị đơn:

let name = "Michal";  
AsyncStorage.setItem('user',name);

Ví dụ duy trì nhiều giá trị trong một đối tượng:

let obj = {  
      name: 'Michal',  
      email: 'michal@gmail.com',  
      city: 'New York',  
    }  
AsyncStorage.setItem('user',JSON.stringify(obj));

Lấy dữ liệu:

React Native AsyncStorage lấy các dữ liệu được lưu sử dụng phương thức getItem() như sau:

await AsyncStorage.getItem('key');

Ví dụ lấy một giá trị đơn:

await AsyncStorage.getItem('user');

Ví dụ lấy nhiều giá trị từ một đối tượng:

let user = await AsyncStorage.getItem('user');  
let parsed = JSON.parse(user);  
alert(parsed.email);

React Native AsyncStorage Ví dụ 1

Trong ví dụ này, chúng ta sẽ tạo 2 thành phần TouchableOpacity, một để lưu và một để lấy dữ liệu. trong thành phần TouchableOpacity đầu tiên, gọi phương thức savaData() để lưu dữ liệu và từ thành phần TouchableOpacity thứ hai, gọi phương thức displayData() để lấy dữ liệu.

import React, {Component} from 'react';  
import {Platform, StyleSheet, Text,  
  View,TouchableOpacity, AsyncStorage,  
} from 'react-native';  
 
export default class App extends Component<Props> {  
  saveData(){  
    let name = "Michal";  
    AsyncStorage.setItem('user',name);  
  }  
  displayData = async ()=>{  
    try{  
      let user = await AsyncStorage.getItem('user');  
      alert(user);  
    }  
    catch(error){  
      alert(error)  
    }  
  }  
  render() {  
    return (  
      <View style={styles.container}>
        <TouchableOpacity onPress ={this.saveData}>
          <Text>Click to save data</Text>
        </TouchableOpacity>    
        <TouchableOpacity onPress ={this.displayData}>
          <Text>Click to display data</Text>
        </TouchableOpacity>
      </View>
    );  
  }  
}  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center',  
    backgroundColor: '#F5FCFF',  
  },  
});

Output:

React Native AsyncStorage Ví dụ 2

Trong ví dụ này, chúng ta sẽ lưu nhiều giá trị trong form nếu đối tượng JSON sử dụng JSON.stringify(). JSON.stringify() lấy đối tượng JavaScript chuyển chúng thành chuỗi JSON. Mặt khác, phương thức JSON.parse() được dùng để lấy dữ liệu AsyncStorage. Phương thức này lấy chuỗi JSON và chuyển nó thành một đối tượng JavaScript trước khi chúng được trả về.

import React, {Component} from 'react';  
import {Platform, StyleSheet, Text,  
  View,TouchableOpacity, AsyncStorage,  
} from 'react-native';  
 
export default class App extends Component<Props> {  
  saveData(){  
    /*let user = "Michal";*/
    let obj = {  
      name: 'Michal',  
      email: 'michal@gmail.com',  
      city: 'New York',  
    }  
    /*AsyncStorage.setItem('user',user);*/
    AsyncStorage.setItem('user',JSON.stringify(obj));  
  }  
  displayData = async ()=>{  
    try{  
      let user = await AsyncStorage.getItem('user');  
      let parsed = JSON.parse(user);  
      alert(parsed.email);  
    }  
    catch(error){  
      alert(error)  
    }  
  }  
  render() {  
    return (  
      <View style={styles.container}>
        <TouchableOpacity onPress ={this.saveData}>
          <Text>Click to save data</Text>
        </TouchableOpacity>    
        <TouchableOpacity onPress ={this.displayData}>
          <Text>Click to display data</Text>
        </TouchableOpacity>
      </View>
    );  
  }  
}  
 
const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    alignItems: 'center',  
    backgroundColor: '#F5FCFF',  
  },  
});

Output:

2. Các phương thức AsyncStorage

Có rất nhiều các phương thức của lớp React Native AsyncStorage được mô tả như ở dưới đây:

Các phương thức

static setItem(key: string, value: string, [callback]: ?(error: ?Error)=>void)

Phương thức setItem() đặt giá trị của một key và gọi một callback khi biên dịch. Nó trả về một đối tượng Promise.

static getItem(key: string, [callback]: ?(error: ?Error, result: ?string)) =>void)

Phương thức getItem() lấy một item từ một key và gọi một callback khi hoàn thành. Nó trả về một đối tượng Promise.

static removeItem(key: string, [callback]: ?(error: ?Error) => void)

Phương thức removeItem() loại bỏ một item cho một key và gọi một callback khi biên dịch. Nó trả về một đối tượng Promise.

static mergeItem(key: string, value: string, [callback]: ?(error: ?Error) => void)

Phương thức mergeItem() sáp nhập các giá trị của khóa với giá trị nhập và cho rằng cả 2 giá trị là JSON đã được chuỗi hóa. Nó trả về một đối tượng Promise.

Chú ý: Phương thức này không được hỗ trợ bởi tất cả các phiên bản native.

static clear([callback]: ?(error: ?Error) => void)

Phương thức clear() xóa bỏ tất cả các AsynchStorage từ các máy khách, thư viện, … Bạn không nên gọi phương thức này, thay vào đó bạn có thể sử dụng removeItem hoặc multiRemove để xóa các khóa của ứng dụng. Nó trả về một đối tượng Promise.

static getAllKeys([callback]: ?(error: ?Error, keys: ?Array<string>) => void)

Nó lấy tất cả các khóa của ứng dụng, cho tất cả các caller, thư viện, … Nó trả về một đối tượng Promise.

static flushGetRequests(): [object Object]

Nó flush bất kỳ yêu cầu đang chờ nào sử dụng một cuộc gọi hàng loạt để lấy dữ liệu.

static multiGet(keys: Array<string>, [callback]: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void)

Phương thức này cho phép bạn lấy hàng loạt các item được đưa ra trong một mảng các input khóa. Phương thức callback sẽ được gọi với một mảng các cặp khóa-giá trị tương ứng được tìm thấy.

multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])

Phương thức này trả về một đối tượng Promise.

static multiSet(keyValuePairs: Array<Array<string>>, [callback]: ?(errors: ?Array<Error>) => void)

Phương thức này được sử dụng như một quy trình xử lý hàng loạt để lưu trữ nhiều cặp khóa-giá trị. Sau khi xử lý xong bạn sẽ co một callback mà không có lỗi.

multiSet([['k1', 'val1'], ['k2', 'val2']], cb);

Phương thức này trả về một đối tượng Promise.

static multiRemove(keys: Array<string>, [callback]: ?(errors: ?Array<Error>) => void)

Phương thức này gọi việc xóa hàng loạt tất cả các khóa trong mảng khóa. Nó trả về một đối tượng Promise.

static multiMerge(keyValuePairs: Array<Array<string>>, [callback]: ?(errors: ?Array<Error>) => void)

Nó thực thi một quy trình hàng loạt để sáp nhập các giá trị đang có với một bộ khóa được cho. Nó cho rằng các giá trị là JSON được chuỗi hóa. Nó trả về một đối tượng Promise.

Một số tài liệu học React Native

Sau đây là một số tài liệu tham khảo để hỗ trợ bạn trong quá trình học React Native:

1. Tài liệu chính thức của React Native

Nếu bạn hỏi một lập trình viên cách để học một cái gì đó thì câu trả lời thường sẽ là “hãy đọc tài liệu đi”. Mình cũng khuyến khích bạn nên làm vậy bởi cách tốt nhất để hiểu cách thức hoạt động của một thứ gì đó là học về các tính năng và logic của nó. Rất may mắn là tài liệu của React Native được viết một cách đơn giản và dễ hiểu và có các ngôn ngữ khác nhau cho bạn lựa chọn.

Bạn có thể truy cập link sau: https://reactnative.dev/docs/getting-started

2. Các cuốn sách

Một cuốn sách hay để bổ trợ cho các khoá học online đó là cuốn FullStack: React Native. Nó là một bản hướng dẫn hoàn thiện về React Native bao gồm tất cả các kiến thức từ các thành phần đến triển khai ứng dụng. Chắc chắn là nó sẽ giúp bạn hiểu rõ hơn về các kiến thức đã học trong các khoá online. Một gợi ý nữa cho bạn đó là cuốn Pete Hunt’s tutorial about ReactJS – Thinking in React. Nó sẽ giúp bạn hiểu rõ hơn về logic React và cơ chế của các thành phần.

Kết luận: Qua đây thì hẳn là các bạn cũng có được một cái nhìn tổng quan về React Native, về khái niệm, những kiến thức cơ bản-nâng cao và các ứng dụng của React Native. Đây không phải là một framework đơn giản nên cần phải có sự nỗ lực lớn từ chính bản thân bạn. Hãy tự tìm tòi, khám phá, tham gia các khoá học, tham khảo các cuốn sách hoặc các bài hướng dẫn trên Youtube và tự bắt tay vào xây dựng các ứng dụng của riêng bạn. Có gì thắc mắc thì các bạn bình luận phía dưới nhé, chúng ta cùng giải quyết.

Chúc bạn may mắn trên con đường chinh phục React Native.

(Visited 25 times, 1 visits today)

TÍN NGHĨA – Đơn vị chuyên cung cấp dịch vụ công nghệ thông tin với chi phí hợp lý nhất, phục vụ cho mọi đối tượng, …

Liên hệ với TINNGHIA ngay hôm nay để có báo giá tốt nhất:
Email: tinnghiaco39@gmail.com – Hotline: 0915.631.868 – 0986.020.123
Webiste: www.tinnghiaco.com
Facebook: facebook.com/dntinnghia
Trong trường hợp tổng đài BẬN LIÊN TỤC hoặc QUÁ TẢI đơn hàng, Quý khách vui lòng để lại thông tin của mình thông qua biểu mẫu liên hệ hoặc tin nhắn để TINNGHIA liên hệ lại và giải đáp mọi thắc mắc của Quý khách trong thời gian sớm nhất.
Xin chân thành cảm ơn Quý khách đã quan tâm tới dịch vụ của TINNGHIA./.