兄弟组件通信—state
List/index.jsx
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>欢迎使用,输入关键字,随后点击搜索</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>
)
}
}
Search/index.jsx
import React, { Component } from 'react'
import axios from 'axios'
export default class Search extends Component {
search = ()=>{
//获取用户的输入(连续解构赋值+重命名)
const {keyWordElement:{value:keyWord}} = this
//发送请求前通知App更新状态
this.props.updateAppState({isFirst:false,isLoading:true})
//发送网络请求
axios.get(`/api1/search/users?q=${keyWord}`).then(
response => {
//请求成功后通知App更新状态
this.props.updateAppState({isLoading:false,users:response.data.items})
},
error => {
//请求失败后通知App更新状态
this.props.updateAppState({isLoading:false,err:error.message})
}
)
}
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用户</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
App.jsx
import React, { Component } from 'react'
import Search from './components/Search'
import List from './components/List'
// 因为他叫index,所以后面的我们可以不写了
export default class App extends Component {
state = {
users: [], //初始化状态,users初始值为数组
isFirst: true, //是否为第一次展开
isLoading: false, //是否处于加载中,发送请求前为true,一旦数据回来了就显示为true
err:'' //存储请求相关的错误信息
}
// 名人名言:状态在哪,操纵状态的方法就在哪里
// saveUsers = (users) => {
// this.setState({
// users
// })
// }
// changeFirst = (users) => {
// this.setState({
// users
// })
// }
// changeisLoading = (users) => {
// this.setState({
// users
// })
// }
// saveerr = (users) => {
// this.setState({
// users
// })
// }
// 这4个函数都要传给search
// 但是这样写太麻烦了,写的可以更加通用一些
// 更新App的state
updateAppState = (stateObj) => {
this.setState(stateObj)
}
render() {
// const {users,isFirst,isLoading,err} = this.state
return (
<div className="container">
{/* <Search saveUsers={this.saveUsers}/> */}
<Search updateAppState={ this.updateAppState}/>
{/* 父给子通过props传函数 */}
{/* <List users={this.state.users} /> */}
<List {...this.state} />
{/* 可以这么写,批量传递——你有多少个我就传多少个 */}
{/* <List users={users} isFirst={isFirst} isLoading={isLoading} err={err} /> */}
{/* 这样写不好,我不能有10个状态,就传10个状态吧 */}
{/* 传过来的数据交给List做展示 */}
</div>
)
}
}
兄弟组件通信–PubSub
List/index.jsx
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
import './index.css'
export default class List extends Component {
state = { //初始化状态
users:[], //users初始值为数组
isFirst:true, //是否为第一次打开页面
isLoading:false,//标识是否处于加载中
err:'',//存储请求相关的错误信息
}
componentDidMount(){
this.token = PubSub.subscribe('atguigu',(_,stateObj)=>{
this.setState(stateObj)
})
}
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
render() {
const {users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</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>
)
}
}
Search/index.jsx
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
//发送请求前通知List更新状态
PubSub.publish('atguigu',{isFirst:false,isLoading:true})
//发送网络请求
axios.get(`/api1/search/users?q=${keyWord}`).then(
response => {
//请求成功后通知List更新状态
PubSub.publish('atguigu',{isLoading:false,users:response.data.items})
},
error => {
//请求失败后通知App更新状态
PubSub.publish('atguigu',{isLoading:false,err:error.message})
}
)
}
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用户</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
App.jsx
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>
)
}
}
消息订阅与发布机制
1.先订阅,再发布(理解:有一种隔空对话的感觉)
2.适用于任意组件间通信
3.要在组件的componentWillUnmount中取消订阅