Fetch
是一種Promise的異步處理機制,用於簡化多層的函數callback 可跨伺服器跟後端程式溝通,AJAX的進化版本
範例:獲取及展示資料
//home.js
//(省略)
const SERVER_URL = 'http://localhost:3000/';
const PRODUCT_API = 'products/';
//載入畫面後才執行載入資料
componentDidMount() {
this._fetchProducts();
}
//獲取資料
_fetchProducts = () => {
//建立request
const req = new Request(SERVER_URL + PRODUCT_API, {method: 'GET'});
//使用request取值
fetch(req).then((res) => {
//將返回的資料轉換成json格式
return res.json();
}).then((result, done) => {
//若有取得資料
if (!done) {
//將資料儲存在手機內
this._saveProducts(result);
//更改state的狀態
this.setState({isNetworkValid: true, products: result});
}
}).catch((err) => {
// 連線異常的處理方式(取手機內資料)
const products = this._queryProducts();
// 顯示錯誤訊息
console.log('products: ' + JSON.stringify(products));
//更改state狀態(會影響後續資料顯示)
this.setState({isNetworkValid: false, products: products});
});
}
//展示資料(局部)
_renderRow = (product) => {
// 判斷網路是否正常,決定圖片載入的方式
const ImageComponent = this.state.isNetworkValid
? <Thumbnail square size={40} source={{
uri: SERVER_URL + product.image
}}/>
: <Thumbnail square size={40} source={require('./images/product-image-01.jpg')}/>;
return (
<ListItem button onPress={() => {
const {navigator} = this.props;
if (navigator) {
//正常情況下方資料是動態賦值
navigator.push({
name: 'detail',
component: Detail,
//透過此處參數的設定,可傳到子頁面
params: {
//資料
product: product,
//更新程式(傳入子元件執行)
productUpdated: this._productUpdated
}
});
}
}}>
{ImageComponent}
<Text>{product.title}</Text>
<Text note>{product.subTitle}</Text>
</ListItem>
);
}
//當子元件(頁面)觸發productUpdated,會執行此父元件函數
//此函數會重新從伺服器取值
_productUpdated = () => {
this._fetchProducts();
}
//(省略)
範例:新增修改刪除資料
//detail.js
//(省略)
constructor(props) {
super(props)
//將父頁面傳入的props存入此元件的state
//每個產品元件都有自己的state
this.state = {
productID: '' + this.props.product.id,
productTitle: this.props.product.title,
productSubTitle: this.props.product.subTitle
}
}
<View style={styles.container}>
<TouchableOpacity onPress={this._pressBackButton.bind(this)}>
<Text style={styles.back}>返回</Text>
</TouchableOpacity>
//(省略表單)
<Button title='保存' onPress={this._updateProduct}></Button>
<Button title='新建' onPress={this._createProduct}></Button>
<Button title='删除' onPress={this._deleteProduct}></Button>
</View>
//更新
_updateProduct = () => {
//更新URL要傳入ID
const req = new Request(SERVER_URL + PRODUCT_API + this.state.productID, {
//若是部份更新用patch
method: 'PUT',
headers: {
// 請求的表頭為JSON
'Accept': 'application/json',
'Content-Type': 'application/json'
},
//要更新的資料
body: JSON.stringify({
'id': parseInt(this.state.productID),
'title': this.state.productTitle,
'subTitle': this.state.productSubTitle,
'image': this.props.product.image
})
});
fetch(req).then((res) => {
return res.json();
}).then((result, done) => {
if (!done) {
this.props.productUpdated();
Alert.alert('保存成功', null, null);
} else {
Alert.alert('保存失败', null, null);
}
});
}
//新增
_createProduct = () => {
const req = new Request(SERVER_URL + PRODUCT_API, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
//要新增的資料
body: JSON.stringify({
'id': parseInt(this.state.productID),
'title': this.state.productTitle,
'subTitle': this.state.productSubTitle,
'image': this.props.product.image
})
});
fetch(req).then((res) => {
return res.json();
}).then((result, done) => {
if (!done) {
//新增後執行更新到資料庫
this.props.productUpdated();
Alert.alert('新建成功', null, null);
} else {
Alert.alert('新建失败', null, null);
}
});
}
//刪除
_deleteProduct = () => {
//刪除要提供ID
const req = new Request(SERVER_URL + PRODUCT_API + this.state.productID, {method: 'DELETE'});
fetch(req).then((res) => {
// 此时返回的数据不是JSON格式,所以不做处理
return res;
}).then((result, done) => {
if (!done) {
//刪除後執行更新到資料庫
this.props.productUpdated();
Alert.alert('删除成功', null, null);
} else {
Alert.alert('删除失败', null, null);
}
});
}
//回上一頁
_pressBackButton() {
//用props直接取得navigator元件
const {navigator} = this.props;
if (navigator) {
navigator.pop();
}
}
//(省略)
Last updated