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