本系列目錄
點贊是美德 : )
React 快速上手 – 09 資料請求 fetch
本文重點在 fetch
基礎使用、配置、實戰,如果你很熟練了,可以直接 pass
目標
- 掌握
fetch
使用- 基礎使用
- 詳細配置
- 同步請求
- 跨平臺 cross-fetch
環境
- react 16.3.2
- fetch 內建
- cross-fetch 2.2.0
1 fetch 基礎使用
1.1 資料結構
我在 easy-mock
上準備了模擬資料
www.easy-mock.com/mock/59801f…
[
{
"id": "610000200102261253",
"name": "薛洋"
},
{
"id": "350000199603020600",
"name": "許磊"
},
{
"id": "310000198105081812",
"name": "崔娟"
},
{
"id": "820000197101010860",
"name": "石霞"
}
]
複製程式碼
一個列表,兩個欄位 id
name
1.2 讀取
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/all`
)
.then(res => res.json())
.then(data => {
console.log(data)
this.setState({users: data})
})
.catch(e => console.log(`錯誤:`, e))
複製程式碼
fetch
是瀏覽器內建物件,所以我們不用安裝包,直接使用
- 使用流程
- fetch …
- then => res.json()
- then => data
注意需要執行一次
res.json()
方法才能獲取資料
1.3 列印
我們獲取資料後,設定 state
,然後正常資料 render
就行,完整程式碼
import React, {Component} from `react`
class RequestView extends Component {
constructor(props) {
super(props)
this.state = {users: []}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/all`
)
.then(res => res.json())
.then(data => {
console.log(data)
this.setState({users: data})
})
.catch(e => console.log(`錯誤:`, e))
}
render() {
return (
<div>
<input type="button" value="點選 http-get 方式獲取資料" onClickCapture={this.handleClick} />
<ul>
{this.state.users &&
this.state.users.map((item, index) => (
<li key={index.toString()}>{item.name}</li>
))}
</ul>
</div>
)
}
}
複製程式碼
列印
- codepen
2 fetch 配置
我們來好好的看下這個 fetch()
全域性方法
我舉兩個自定義例子,大家體會下
2.1 form 提交
2.1.1 定義 Headers
請求頭協議說明
let initHeaders = new Headers()
initHeaders.append(`Accept`, `application/json, text/plain, */*`)
initHeaders.append(`Cache-Control`, `no-cache`)
initHeaders.append(`Content-Type`, `application/x-www-form-urlencoded`)
複製程式碼
- 因為是表單,所以設定
application/x-www-form-urlencoded
2.1.2 定義 init
配置
let data = {uid: 1011}
let body = `uid=${data.uid}`
const init = {
method: `POST`,
credentials: `include`, // cookies
cache: `no-cache `, // cookies
headers: initHeaders,
body
}
複製程式碼
method
指定POST
方式credentials: `include`
表示每次都帶上cookies
headers
請求頭協議說明body
資料,格式key=val&key=val&key=val
2.1.3 請求提交
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/login`,
init
)
.then(res => res.json())
.then(data => {
this.setState({user: data})
})
.catch(e => console.log(`錯誤:`, e))
複製程式碼
這裡就類似我們第一個基礎例子了
- codepen
2.2 raw 提交
2.2.1 定義 Headers
let initHeaders = new Headers()
initHeaders.append(`Accept`, `application/json, text/plain, */*`)
initHeaders.append(`Cache-Control`, `no-cache`)
initHeaders.append(`Content-Type`, `application/json;charset=UTF-8`)
複製程式碼
Content-Type
型別需要定義成application/json;charset=UTF-8
2.2.2 定義 init
let data = {uid: 1011}
let body = JSON.stringify(data, null, 2)
const init = {
method: `POST`,
credentials: `include`, // cookies
cache: `no-cache `, // cookies
headers: initHeaders,
body
}
複製程式碼
json
資料需要格式化JSON.stringify(data, null, 2)
2.2.3 請求提交
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/login`,
init
)
.then(res => res.json())
.then(data => {
this.setState({user: data})
})
.catch(e => console.log(`錯誤:`, e))
複製程式碼
- codepen
2.3 完整例子
程式碼
import React, {Component} from `react`
class RequestView extends Component {
constructor(props) {
super(props)
this.state = {user: null}
this.handlePostForm = this.handlePostForm.bind(this)
this.handlePostJSON = this.handlePostJSON.bind(this)
}
handlePostForm() {
let initHeaders = new Headers()
initHeaders.append(`Accept`, `application/json, text/plain, */*`)
initHeaders.append(`Cache-Control`, `no-cache`)
initHeaders.append(`Content-Type`, `application/x-www-form-urlencoded`)
let data = {uid: 1011}
let body = `uid=${data.uid}`
const init = {
method: `POST`,
credentials: `include`, // cookies
cache: `no-cache `, // cookies
headers: initHeaders,
body
}
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/login`,
init
)
.then(res => res.json())
.then(data => {
this.setState({user: data})
})
.catch(e => console.log(`錯誤:`, e))
}
handlePostJSON() {
let initHeaders = new Headers()
initHeaders.append(`Accept`, `application/json, text/plain, */*`)
initHeaders.append(`Cache-Control`, `no-cache`)
initHeaders.append(`Content-Type`, `application/json;charset=UTF-8`)
let data = {uid: 1011}
let body = JSON.stringify(data, null, 2)
const init = {
method: `POST`,
credentials: `include`, // cookies
cache: `no-cache `, // cookies
headers: initHeaders,
body
}
fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/login`,
init
)
.then(res => res.json())
.then(data => {
this.setState({user: data})
})
.catch(e => console.log(`錯誤:`, e))
}
render() {
return (
<div>
<input
type="button"
value="點選 http-post form 表單"
onClickCapture={this.handlePostForm}
/>
<br />
<input
type="button"
value="點選 http-post json raw 格式"
onClickCapture={this.handlePostJSON}
/>
{this.state.user && (
<ul>
<li>ID: {this.state.user.id}</li>
<li>Name: {this.state.user.name}</li>
</ul>
)}
</div>
)
}
}
export default RequestView
複製程式碼
動圖效果
3 fetch 同步 async / wait
3.1 同步寫法
async handleClick() {
try {
const res = await fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/all`
)
const users = await res.json()
this.setState({users})
} catch (error) {
console.log(`錯誤`, error)
}
}
複製程式碼
- 函式本身要定義成
async
res.json()
這個方法不要忘記呼叫- 異常處理要用
try ... catch ...
3.2 完成例子
程式碼
import React, {Component} from `react`
class RequestView extends Component {
constructor(props) {
super(props)
this.state = {users: []}
this.handleClick = this.handleClick.bind(this)
}
async handleClick() {
try {
const res = await fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/all`
)
const users = await res.json()
this.setState({users})
} catch (error) {
console.log(`錯誤`, error)
}
}
render() {
return (
<div>
<input
type="button"
value="點選 async / await 方式獲取資料"
onClickCapture={this.handleClick}
/>
<ul>
{this.state.users &&
this.state.users.map((item, index) => (
<li key={index.toString()}>{item.name}</li>
))}
</ul>
</div>
)
}
}
export default RequestView
複製程式碼
列印
4 fetch 相容性
好像 fetch
很強啊,不用安裝包,全域性方法直接用,但是有一個小問題,對瀏覽器的依賴,先看下 caniuse 平臺的報告:
IE
全陣亡,低版本 Safari
相容問題,Firefox
Chrome
Opera
如果特性不開的話也會出問題,懂的同學說可以瀏覽器配置和打 polyfill
補丁,但是這樣需要自己做很多工作,如果你的程式碼需要跑到 node
端呢(因為API 業務層
很有可能複用性很高)。
如果考慮相容性,所以我們還是用第三方元件
5 cross-fetch 元件
5.1 介紹
感覺 Star
不是很多麼。。。
接著往下看
5.2 多平臺支援
README 裡說了各種平臺支援、知名專案也在用
是真的麼。。。
接著往下看
5.3 包研究
開啟檔案 package.json
來看下這兩個包
- node-fetch
- whatwg-fetch
指向了 github/fetch
- github/fetch
好多 Star 看著就放心,大家用吧
5.4 例子
- 安裝
yarn add cross-fetch
複製程式碼
- 程式碼
import React, {Component} from `react`
import fetch from `cross-fetch`
class RequestView extends Component {
constructor(props) {
super(props)
this.state = {users: []}
this.handleClick = this.handleClick.bind(this)
}
async handleClick() {
try {
const res = await fetch(
`https://www.easy-mock.com/mock/59801fd8a1d30433d84f198c/example/user/all`
)
const users = await res.json()
this.setState({users})
} catch (error) {
console.log(`錯誤`, error)
}
}
render() {
return (
<div>
<input
type="button"
value="點選 cross-fetch 元件方式 獲取資料"
onClickCapture={this.handleClick}
/>
<ul>
{this.state.users &&
this.state.users.map((item, index) => (
<li key={index.toString()}>{item.name}</li>
))}
</ul>
</div>
)
}
}
export default RequestView
複製程式碼
- 列印
程式碼
參考
© 會煮咖啡的貓咪