react兄弟组件通信之pubsub-js

-

在未接触redux之前,兄弟组件之间共享状态,需要把状态提升到公共的父组件,然后父组件用props传给子组件,实现兄弟组件状态共享。

还有一种方法可实现兄弟组件的通信,pubsub-js

npm地址:https://www.npmjs.com/package/pubsub-js

pubsub-js就是消息发布订阅,实现这个功能的有很多库

vue2的$bus、mitt.js都是一样的原理,个人觉得比pubsub-js使用起来更加方便

这里用一下pubsub-js

Search组件内 发布消息

import React, { Component } from 'react'
import PubSub from 'pubsub-js'
import axios from 'axios';

export default class Search extends Component {
  search = () => {
    // 获取用户输入
    const { value: keyWord } = this.keyWordElement;
    // 消息发布
    // 发送请求前通知List更新状态
    PubSub.publish('updateListState', { isFirst: false, isLoading: true, err: '' })
    // 获取网络请求
    axios.get(`https://api.github.com/search/users?q=${keyWord}`).then(
      res => {
        PubSub.publish('updateListState', { users: res.data.items, isLoading: false  })
      },
      err => {
        // 请求失败后通知List更新错误信息状态
        PubSub.publish('updateListState', { err: err.message, isLoading: false })
      }
    )
  }
  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>
    )
  }
}

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('updateListState', (_, stateObj) => {
      this.setState(stateObj);
    })
  }
  componentWillUnmount() {
    // 取消订阅
    PubSub.unsubscribe(this.token)
  }
  render() {
    const { users, isFirst, isLoading, err } = this.state;
    return (
      isFirst ? <h2>欢迎使用,输入关键字,然后点击搜索</h2> :
      isLoading ? <h2>Loading......</h2> :
      err ? <h2 style={{ color: 'red' }}>{err}</h2> :
      <div className="row">
        {
          users.map(userObj => {
            return (
              <div className="card" key={userObj.id}>
                <a href={userObj.html_url} target="_blank">
                  <img src={userObj.avatar_url} style={{width: '100%'}} />
                </a>
                <p className="card-text">{userObj.login}</p>
              </div>
            )
          })
        }
      </div>
    )
  }
}

 

 

 

-

 

 

 

 

 

-

posted @ 2022-09-27 22:21  古墩古墩  Views(623)  Comments(0Edit  收藏  举报