react-native&android 之開發問題篇一

學術袁發表於2018-07-05

react-native 開發過程中引入別人的react-native-x庫,環境上會有某種不通過。
著實很憂愁,下面就以我遇到的問題排下名詞;

MEET 壹

Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute meta-data#android.support.VERSION@value value=(26.1.0) from [com.android.support:exifinterface:26.1.0] AndroidManifest.xml:25:13-35
    is also present at [com.android.support:appcompat-v7:26.0.2] AndroidManifest.xml:28:13-35 value=(26.0.2).
    Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml:23:9-25:38 to override.

該問題出現原因是,AndroidManifest.xml合併過程中,由於com.android.support:appcompat版本不同導致無法成功合併;
solution:一股腦的把所依賴的react-native-x庫等影響因素全部搞一致,按照我的經驗,也並不一定把所有的依賴庫的都搞一致。但是更重要的是你要判斷出上面報錯針對的是哪一個依賴庫的。注意:按照上面日誌的版本要求做。因為在一些react-native庫中在實現功能上,要求的版本較高;

如下

compileSdkVersion 26
buildToolsVersion "26.0.2"
compile 'com.android.support:appcompat-v7:26.1.0'

MEET 貳

這裡寫圖片描述

Error:Could not find common.jar (android.arch.core:common:1.0.0).
Searched in the following locations:
    https://jcenter.bintray.com/android/arch/core/common/1.0.0/common-1.0.0.jar

該問題出現原因是, jcenter已經刪掉了android.arch.core庫,所以需要從 maven { url “https://maven.google.com” }中獲取android.arch.core:common-1.1.0.jar
solution:在project工程根目錄下add程式碼指令maven { url "https://maven.google.com" }
如下:

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        //解決問題:Error:Failed to resolve: android.arch.core:common:1.1.0
        maven { url "https://maven.google.com" }
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

MEET 叄

這裡寫圖片描述

undefined is not an object (evaluating 'this.props.navigation.goBack')

這裡出現的問題是,我從react-native首頁面HomeScreen.js中點選某個按鈕。通過

import {StackNavigator,NavigationActions} from 'react-navigation';

this.props.navigation.navigate("GoodsListScreen")命令進入到一個新的列表,在新的Component頁面中引入了一個自定義的TitleBar,就是這樣的

export default class GoodsListScreen extends Component {
...
render() {
        return (<View style={styles.container}>
            <TitleBar
                /** {...this.props} 加上這一行就對了*/ 
                title = "育嬰"
                headerBar = {{backgroundColor:Colors.black}}
                statusBar = {{backgroundColor:Colors.black}}
            />
            ...
        </View>);
    }
}

點選返回按鈕,想要返回到上一個頁面,就報錯了
該問題出現原因是,undefined is not an object。結合上面圖片,說明this.props.navigation是null。也就是說,頁面元件屬性this.props沒有傳到子元件中。
solution: TitleBar 標籤中新增屬性 {…this.props},可在子元件解構賦值。


MEET 肆

這裡寫圖片描述

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
大概意思:只能更新已裝載或裝載過的元件。側面說明你在這樣未裝載的元件上呼叫setState、replaceState或forceUpdate是不行滴。

我是怎麼編出這樣的程式碼邏輯的:寫了一個demo例子,在react-native版本0.51.0下。對元件FlatList實現下拉重新整理和上拉載入更多。但是在快速滑動頁面,直接就載入了n多個item資料,並且中間一大段是空白,然後下邊很快提示了上面的警告!
然後也看到官網上也有這方面的簡單提示:

為了優化記憶體佔用同時保持滑動的流暢,列表內容會在螢幕外非同步繪製。這意味著如果使用者滑動的速度超過渲染的速度,則會先看到空白的內容。這是為了優化不得不作出的妥協,而我們也在設法持續改進。

solution: 對元件FlatList新增屬性

                onEndReachedThreshold={0.1}
                initialNumToRender={3}
                getItemLayout={(data, index) => ({
                    length: 250, offset: (250 + 10) * index, index
                })}

onEndReachedThreshold滑動到距離底部距離0.1*item高度開始載入更多;
initialNumToRender首次進入渲染**3個**item;
getItemLayout避免動態測量內容尺寸的開銷;
解決了問題。原始碼地址分支blog0706


MEET 伍

這裡寫圖片描述

Cannot add child that doesn't have a YogaNode to a parent without a measure function.

//正確程式碼
render() {
        return (<View style={{flex: 1, backgroundColor: Colors.bg}}>
            <FlatList
                ref={(flatlist) => this.flatlist = flatlist}
                ListHeaderComponent={this._header}
                renderItem={this._renderItem}
                ItemSeparatorComponent={this.props.itemSeparator}
                data={this.state.dataSource}
                keyExtractor={this._keyExtractor}
                onRefresh={() => this.onRefresh()}
                refreshing={this.state.isRefresh}
                onEndReachedThreshold={10}
                onEndReached={
                    () => this.onLoadMore()
                }
            />
            <Toast ref='toast'/>
        </View>);
    }

solution:我的問題出現的就是<Toast ref='toast'/>直接放在了上面程式碼塊中,它所在行的上一行的'/>'的後面導致。這樣竟然也能搞出錯誤,當然,有的部落格上說在render方法中一些註釋也會導致這種問題!


MEET 陸

這裡寫圖片描述

undefined is not an object (evaluating '_react2.PropTypes.string')

我的程式碼是這樣的,然出現上面的錯誤

/**
 * 功能:自定義的樣式Button按鈕
 * Created by YJH on 2018/7/10.
 */
import React, { Component,PropTypes } from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';

export default class Button extends Component {
    static propTypes = {
        text: PropTypes.string.isRequired,
        onClick: PropTypes.func.isRequired,
    };

    render() {
        const { text, onClick } = this.props;
        return (
            <TouchableOpacity style={styles.Button}  onPress={onClick}>
                <Text>{text}
                </Text>
            </TouchableOpacity>
        )
    }
}

const styles = StyleSheet.create({
    Button: {
       ...
    }
});

該問題出現原因是,ReactNative的Framework升級到0.50.3後,使用上面的引入方式就不能使用了。
依照我的專案,正確的引入方式是,import PropTypes from '../../../../../node_modules/prop-types/';
solution: PropTypes這個屬性移動到了依賴的node_modules中**,再正確引入即可;

相關文章