11.React兄弟组件通信

本文探讨了React应用中如何使用PubSub.js实现组件间的通信,通过`isFirst`、`isLoading`和`err`状态的传递,展示了如何在`Search`组件触发请求时更新`List`组件的状态,实现轻量级的父子组件间通信方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

兄弟组件通信—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="输入关键词点击搜索"/>&nbsp;
					<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="输入关键词点击搜索"/>&nbsp;
					<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中取消订阅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值