第四章 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 . statereturn ( < 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" > < imgalt= "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> < inputref= { ( 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" > < imgalt= "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> < inputref= { ( 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" > < imgalt= "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> < inputref= { ( 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) ; }