第四章 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} } = thisconsole.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" /> <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} } = thisaxios.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" /> <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"/> <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"/> <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}} = thisPubSub.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"/> <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);}