ReactNative開發入門教學(3)-與伺服器溝通(Fetch)
如果我們今天要從伺服器上取得資料的話,我們知道 javascript 有提供 ajax 的寫法,
不過,在 ReactNative 中我們大可不必寫 ajax ,我們可以用 fetch() 來連上我們的伺服器
並取得資料! fetch() 的用法可以參考官網 https://facebook.github.io/react-native/docs/network.html
試試看吧!我想沿用上次的代碼,然後我再伺服器上用PHP架好了一個API,被呼叫後回傳個JSON
內容是「{“Message”:”Clicked!”}」。這樣的話我們先照著官網的方式寫個 fetch() 吧!
import React, { Component } from 'react';
import {
Text,
View,
TouchableHighlight,
Button,
} from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
_click() {
fetch('https://xxxxxxxxxxxxxxxxxx', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
Param: 'aaa',
})
});
}
render() {
return(
<View>
<Button title="Try it!" onPress={this._click.bind(this)}/>
<TouchableHighlight onPress={this._click.bind(this)}>
<Text>HelloWorld!</Text>
</TouchableHighlight>
</View>
);
}
}
export default App;
接著點擊看看會發現沒有任何的反應。是的。因為我們並沒有對傳回的東西做任何的處理。
所以我們在修改一下。
_click() {
fetch('https://xxxxxxxxxxxxxxxxxx', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
Param: 'aaa',
})
}).then((response) => response.json())
.then((responseJson) => {
return responseJson.Message;
})
.catch((error) => {
console.error(error);
});
}
執行後是否就可以取到伺服器傳回來的JSON值囉!
但是我們大部分會傳一些參數過去給伺服器,例如我要登入某些資料之類的。
在上面會看到有Param這個參數,但那只是我隨便亂打的,伺服器並不會對它有任何
的反應。如果我今天在PHP上想用POST或是GET來收參數的話。用上面的寫法會發現
參數並沒有被傳到伺服器,那是因為我們一般HTML在執行POST或是GET的時候,表頭
並不是json,而是 x-www-form-urlencoded 。這相關的知識我也不懂,也是碰到
這個問題的時候才去查的!所以要把代碼改成如下
_click() {
fetch('https://xxxxxxxxxxxxxxxxxx', {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify({
Param: 'aaa',
})
}).then((response) => response.json())
.then((responseJson) => {
return responseJson.Message;
})
.catch((error) => {
console.error(error);
});
}
結果發現改了之後參數還是一樣沒有傳過去,後來繼續上網爬文,得知用
JSON.stringify() 的話並不是像我們平常用的POST或是GET的方式傳給伺服器
所以我們得寫個把參數變成像是 https://xxxxx?Param=aaa 之類的方法。方法
to_query_string = (obj) => {
return obj ? Object.keys(obj).sort().map((key) => {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map((val2) => {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
}
然後最後成功的完整代碼會是下面這樣
import React, { Component } from 'react';
import {
Text,
View,
TouchableHighlight,
Button,
} from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
_click() {
fetch('https://xxxxxxxxxxxxxxxxxx', {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: to_query_string({
Param: 'aaa',
})
}).then((response) => response.json())
.then((responseJson) => {
return responseJson.Message;
})
.catch((error) => {
console.error(error);
});
}
render() {
return(
<View>
<Button title="Try it!" onPress={this._click.bind(this)}/>
<TouchableHighlight onPress={this._click.bind(this)}>
<Text>HelloWorld!</Text>
</TouchableHighlight>
</View>
);
}
}
to_query_string = (obj) => {
return obj ? Object.keys(obj).sort().map((key) => {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map((val2) => {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
}
export default App;