變量保護
出現最多的就是在使用redux來做數據層,使用this.props的屬性沒有去查詢時候爲undefined,這種情況,基本是必crash
比如下例:
//show user name
<Text>{this.props.userInfo.name}</Text>
如果userInfo爲undefined的話,就會崩潰,錯誤如下:
TypeError: Cannot read property ‘name’ of undefined
在這裏name爲undefined的時候反而沒有問題,因爲name是一個簡單的屬性,直接賦值給Text是沒有問題的。
那如何避免這種問題呢?在賦值前加下判斷會比較好:
let name = this.props.userInfo && this.props.userInfo.name ? this.props.userInfo.name : '';
//show user name
<Text>{this.props.userInfo.name}</Text>
這樣基本可以避免崩潰的問題了。
但是如果都這樣判斷,實際是比較複雜的,所以如果你的業務比較簡單,我建議可以直接在render做一個大的保護,即沒有數據的時候,不去render這些業務內容.
思路如下:
render(){
if(!this.props.userInfo){
return (
<EmptyView />
)
} else {
return (
//注意,如果name的層級更深,還是建議做保護
<Text>{this.props.userInfo.name}</Text>
)
}
}
定時器
定時器其實在iOS中也是一個非常容易出問題的地方,crash率會比較高。究其原因,我想是主要是因爲定時器存在一個事件發生的延後性(廢話嘛0_o),但是很多時候會忘記,當定時任務真的發生的時候,語境變化了嗎?如果語境都已經被dealloc了,定時任務仍然被激活,系統就會憤怒地罷工了。
比如:
componentDidMount() {
setTimeout(
() => { console.log('這就可能會崩潰'); },
500
);
}
如果500ms之內,這個component就會Unmount了,那直接回崩潰。RN官方的建議如下:
TimerMixin
爲了解決這個問題,我們引入了TimerMixin。如果你在組件中引入TimerMixin,就可以把你原本的setTimeout(fn, 500)改爲this.setTimeout(fn, 500)(只需要在前面加上this.),然後當你的組件卸載時,所有的計時器事件也會被正確的清除。
這個庫並沒有跟着React Native一起發佈。你需要在項目文件夾下輸入npm i react-timer-mixin –save來單獨安裝它。
var TimerMixin = require('react-timer-mixin');
var Component = React.createClass({
mixins: [TimerMixin],
componentDidMount: function() {
this.setTimeout(
() => { console.log('這樣我就不會導致內存泄露!'); },
500
);
}
});
代碼保護(推薦)
Mixin屬於ES5語法,對於ES6代碼來說,無法直接使用Mixin。如果你的項目是用ES6代碼編寫,同時又使用了計時器,那麼你只需銘記在unmount組件時清除(clearTimeout/clearInterval)所有用到的定時器,那麼也可以實現和TimerMixin同樣的效果。例如:
import React,{
Component
} from 'react';
export default class Hello extends Component {
componentDidMount() {
this.timer = setTimeout(
() => { console.log('把一個定時器的引用掛在this上'); },
500
);
}
componentWillUnmount() {
// 如果存在this.timer,則使用clearTimeout清空。
// 如果你使用多個timer,那麼用多個變量,或者用個數組來保存引用,然後逐個clear
this.timer && clearTimeout(this.timer);
}
};
我今天看了我們項目的代碼,發現幾乎沒有人做保護,代碼copy的現象,真的是令人髮指,可能很多人都沒仔細看過官方的文檔。。。
RN0.43 Text組件bug
最近公司升級了RN的版本,從0.39升級到了0.43,這裏出現了一個比較嚴重的bug。github上的issue地址:[https://github.com/facebook/react-native/issues/13080
](https://github.com/facebook/react-native/issues/13080
)
具體來說,就是android
上面的Text
,string和int等數值混排會出現莫名的bug,無論Text是否加了點擊事件,只要觸摸int等數值的展示部分,就會崩潰,具體代碼如下:
let num = 5;
<Text>有{num}個贊</Text> //點擊crash
如何補救呢?使用.toString
:
let num = 5;
<Text> 有{num.toString()}個贊</Text> //ok
看github上的記錄,0.44已經修復,但是如果使用0.43的同學,千萬要小心。
更新於 2017-05-10
字符串作爲判斷條件 崩潰bug
類似這樣:
let test = {string: ''};
return (
<View>
{test && test.string &&
<Text>{test.string}</Text>
}
</View>
)
報錯:
Error: RawText "" must be wrapped in an explicit <Text> component.
原因未知,但是會崩潰
保護措施:
let test = {string: ''};
return (
<View>
{test && !!test.string &&
<Text>{test.string}</Text>
}
</View>
)
具體的可以看下這篇文章:Error RawText ** must be wrapped in an explicit component 問題解決