第四章 React ajax
三、案例 – github 用户搜索
2. 代码实现
2.3 axios 发送请求
Search
import React, { Component } from "react" ;
import axios from 'axios'
export default class Search extends Component {
search = ( ) => {
const { keyWordElement : { value : keyword} } = this
console. log ( keyword) ;
axios. get ( ` https://api.github.com/search/users?q= ${ keyword} ` ) . then (
response => { console. log ( 'c' , response. data) ; } ,
error => { console. log ( 'd' , error) ; }
)
}
render ( ) {
return (
< section className= "jumbotron" >
< h3 className= "jumbotron-heading" > Search Github Users< / h3>
< div>
< input ref= { c => this . keyWordElement = c} type= "text" placeholder= "enter the name you search" / >
& nbsp;
< button onClick= { this . search} > Search< / button>
< / div>
< / section>
) ;
}
}
2.4 展示数据
2.4.1 App
import React, { Component } from "react" ;
import Search from "./components/Search" ;
import List from "./components/List" ;
export default class App extends Component {
state = { users : [ ] }
saveUsers = ( users ) => {
this . setState ( { users} )
}
render ( ) {
const { users} = this . state
return (
< div className= "container" >
< Search saveUsers= { this . saveUsers} / >
< List users= { users} / >
< / div>
) ;
}
}
2.4.2 Search
import React, { Component } from "react" ;
import axios from 'axios'
export default class Search extends Component {
search = ( ) => {
const { keyWordElement : { value : keyword} } = this
axios. get ( ` https://api.github.com/search/users?q= ${ keyword} ` ) . then (
response => {
this . props. saveUsers ( response. data. items)
} ,
error => { console. log ( 'd' , error) ; }
)
}
render ( ) {
return (
< section className= "jumbotron" >
< h3 className= "jumbotron-heading" > Search Github Users< / h3>
< div>
< input ref= { c => this . keyWordElement = c} type= "text" placeholder= "enter the name you search" / >
& nbsp;
< button onClick= { this . search} > Search< / button>
< / div>
< / section>
) ;
}
}
2.4.3 List
import React, { Component } from "react" ;
import "./index.css" ;
export default class List extends Component {
render ( ) {
return (
< div className= "row" >
{ this . props. users. map ( ( userObj ) => {
return (
< div key= { userObj. id} className= "card" >
< a rel= "noreferrer" href= { userObj. html_url} target= "_blank" >
< img
alt= "head_portrait"
src= { userObj. avatar_url}
style= { { width : "100px" } }
/ >
< / a>
< p className= "card-text" > { userObj. login} < / p>
< / div>
) ;
} ) }
< / div>
) ;
}
}
2.5 完成案例
2.5.1 App
import React, { Component } from "react" ;
import Search from "./components/Search" ;
import List from "./components/List" ;
export default class App extends Component {
state = {
users : [ ] ,
isFirst : true ,
isLoading : false ,
err : "" ,
} ;
updateAppState = ( stateObj ) => {
this . setState ( stateObj) ;
} ;
render ( ) {
const { users } = this . state;
return (
< div className= "container" >
< Search updateAppState= { this . updateAppState} / >
< List { ... this . state} / >
< / div>
) ;
}
}
2.5.2 Search
import React, { Component } from "react" ;
import axios from "axios" ;
export default class Search extends Component {
search = ( ) => {
const {
keyWordElement : { value : keyword } ,
} = this ;
this . props. updateAppState ( { isFirst : false , isLoading : true } ) ;
axios. get ( ` https://api.github.com/search/users?q= ${ keyword} ` ) . then (
( response ) => {
this . props. updateAppState ( {
isLoading : false ,
users : response. data. items,
} ) ;
} ,
( error ) => {
this . props. updateAppState ( { isLoading : false , err : error. message } ) ;
}
) ;
} ;
render ( ) {
return (
< section className= "jumbotron" >
< h3 className= "jumbotron-heading" > Search Github Users< / h3>
< div>
< input
ref= { ( c ) => ( this . keyWordElement = c) }
type= "text"
placeholder= "enter the name you search"
/ >
& nbsp;
< button onClick= { this . search} > Search< / button>
< / div>
< / section>
) ;
}
}
2.5.3 List
import React, { Component } from "react" ;
import "./index.css" ;
export default class List extends Component {
render ( ) {
const { users, isFirst, isLoading, err } = this . props;
return (
< div className= "row" >
{ isFirst ? (
< h2> Welcome, enter a keyword and then click search! < / h2>
) : isLoading ? (
< h2> Loading... ... < / h2>
) : err ? (
< h2 style= { { color : "red" } } > { err} < / h2>
) : (
users. map ( ( userObj ) => {
return (
< div key= { userObj. id} className= "card" >
< a rel= "noreferrer" href= { userObj. html_url} target= "_blank" >
< img
alt= "head_portrait"
src= { userObj. avatar_url}
style= { { width : "100px" } }
/ >
< / a>
< p className= "card-text" > { userObj. login} < / p>
< / div>
) ;
} )
) }
< / div>
) ;
}
}
四、消息订阅-发布机制
1. 工具库
2. 下载
npm install pubsub-js --save
3. 使用
import PubSub from ‘pubsub-js’ //引入 PubSub.subscribe(‘delete’, function(data){ }); //订阅 PubSub.publish(‘delete’, data) //发布消息
4. github 用户搜索代码重构
4.1 App
import React, { Component } from "react" ;
import Search from "./components/Search" ;
import List from "./components/List" ;
export default class App extends Component {
render ( ) {
return (
< div className= "container" >
< Search / >
< List / >
< / div>
) ;
}
}
4.2 Search
import React, { Component } from "react" ;
import PubSub from "pubsub-js" ;
import axios from "axios" ;
export default class Search extends Component {
search = ( ) => {
const {
keyWordElement : { value : keyword } ,
} = this ;
PubSub. publish ( "alex" , { isFirst : false , isLoading : true } ) ;
axios. get ( ` https://api.github.com/search/users?q= ${ keyword} ` ) . then (
( response ) => {
PubSub. publish ( "alex" , {
isLoading : false ,
users : response. data. items,
} ) ;
} ,
( error ) => {
PubSub. publish ( "alex" , { isLoading : false , err : error. message } ) ;
}
) ;
} ;
render ( ) {
return (
< section className= "jumbotron" >
< h3 className= "jumbotron-heading" > Search Github Users< / h3>
< div>
< input
ref= { ( c ) => ( this . keyWordElement = c) }
type= "text"
placeholder= "enter the name you search"
/ >
& nbsp;
< button onClick= { this . search} > Search< / button>
< / div>
< / section>
) ;
}
}
4.3 List
import React, { Component } from "react" ;
import PubSub from "pubsub-js" ;
import "./index.css" ;
export default class List extends Component {
state = {
users : [ ] ,
isFirst : true ,
isLoading : false ,
err : "" ,
} ;
componentDidMount ( ) {
this . token = PubSub. subscribe ( "alex" , ( _, stateObj ) => {
this . setState ( stateObj) ;
} ) ;
}
componentWillUnmount ( ) {
PubSub. unsubscribe ( this . token) ;
}
render ( ) {
const { users, isFirst, isLoading, err } = this . state;
return (
< div className= "row" >
{ isFirst ? (
< h2> Welcome, enter a keyword and then click search! < / h2>
) : isLoading ? (
< h2> Loading... ... < / h2>
) : err ? (
< h2 style= { { color : "red" } } > { err} < / h2>
) : (
users. map ( ( userObj ) => {
return (
< div key= { userObj. id} className= "card" >
< a rel= "noreferrer" href= { userObj. html_url} target= "_blank" >
< img
alt= "head_portrait"
src= { userObj. avatar_url}
style= { { width : "100px" } }
/ >
< / a>
< p className= "card-text" > { userObj. login} < / p>
< / div>
) ;
} )
) }
< / div>
) ;
}
}
五、扩展:Fetch
1. 文档
https://github.github.io/fetch/
2. 特点
fetch: 原生函数,不再使用 XmlHttpRequest 对象提交 ajax 请求 老版本浏览器可能不支持
3. 相关 API
3.1 GET 请求
fetch ( url) . then ( function ( response ) {
return response. json ( )
} ) . then ( function ( data ) {
console. log ( data)
} ) . catch ( function ( e ) {
console. log ( e)
} ) ;
3.2 POST 请求
fetch ( url, {
method : "POST" ,
body : JSON . stringify ( data) ,
} ) . then ( function ( data ) {
console. log ( data)
} ) . catch ( function ( e ) {
console. log ( e)
} )
4. github 用户搜索代码 - fetch
Search
import React, { Component } from "react" ;
import PubSub from "pubsub-js" ;
export default class Search extends Component {
search = async ( ) => {
const { keyWordElement : { value : keyWord} } = this
PubSub. publish ( 'alex' , { isFirst : false , isLoading : true } )
try {
const response= await fetch ( ` https://api.github.com/search/users?q= ${ keyWord} ` )
const data = await response. json ( )
PubSub. publish ( 'alex' , { isLoading : false , users : data. items} )
} catch ( error) {
PubSub. publish ( 'alex' , { isLoading : false , err : error. message} )
}
}
render ( ) {
return (
< section className= "jumbotron" >
< h3 className= "jumbotron-heading" > Search Github Users< / h3>
< div>
< input
ref= { ( c ) => ( this . keyWordElement = c) }
type= "text"
placeholder= "enter the name you search"
/ >
& nbsp;
< button onClick= { this . search} > Search< / button>
< / div>
< / section>
) ;
}
}
六、总结
1 .设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办。
2 .ES6小知识点:解构赋值+重命名
let obj = { a:{ b:1} }
const { a} = obj; //传统解构赋值
const { a:{ b} } = obj; //连续解构赋值
const { a:{ b:value} } = obj; //连续解构赋值+重命名
3 .消息订阅与发布机制
1 .先订阅,再发布(理解:有一种隔空对话的感觉)
2 .适用于任意组件间通信
3 .要在组件的componentWillUnmount中取消订阅
4 .fetch发送请求(关注分离的设计思想)
try {
const response = await fetch( ` /api1/search/users2?q= ${ keyWord} ` )
const data = await response.json( )
console.log( data) ;
} catch ( error) {
console.log( '请求出错' ,error) ;
}