Шина событий в React?

В основном я использую Vue, и совсем недавно я освоил React. Мне нравится это до сих пор, и он во многих отношениях очень похож на Vue, что упрощает его изучение.

Теперь давайте рассмотрим компонент двух братьев и сестер. Я хочу вызвать что-то в компоненте номер один, когда что-то происходит в компоненте номер два. В Vue вы можете просто привязать window.bus = new Vue, а затем передать один из компонентов bus.$emit('event') и привязать mounted() второго компонента bus.$on('event', this.doSth).

Как этого добиться в React?

Способ React состоял бы в том, чтобы родительский компонент компонентов передавал обратный вызов одному из компонентов, который вызывает компонент. Затем родительский элемент что-то делает с данными и выполняет повторную визуализацию, передавая данные другому компоненту. Конечно, вы также можете просто использовать любую библиотеку pubsub и напрямую подключать компоненты. Это действительно зависит от вас.

Felix Kling 16.11.2018 01:42

Спасибо за ответ, посмотрю и библиотеки pubsub.

Tomasz Rup 16.11.2018 01:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
12
2
14 034
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

В случае двух родственных компонентов вы должны сохранить состояние в родительском компоненте и передать это состояние в качестве опоры обоим братьям и сестрам:

class ParentComponent extends Component {
  state = {
   specialProp: "bar"
  }

  changeProp = () => {
   // this.setState.. 
  }
  render() {
    return (
      <div>
        <FirstSibling specialProp = {this.state.specialProp} />
        <SecondSibling changeProp = {this.changeProp} specialProp = {this.state.specialProp} />
      </div>
    );
  }
}
Ответ принят как подходящий

Родительский компонент может управлять state и методами, используемыми дочерними компонентами, при передаче через props.

В следующем примере счетчик увеличивается. SibOne отображает счетчик, а кнопка в SibTwo увеличивает счетчик.

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };
    }
    incrementCount = () => {
        this.setState({
            count: this.state.count + 1
        });
    }
    render() {
        return (
            <div className = "App">
                <SibOne count = {this.state.count}/>
                <SibTwo incrementCount = {this.incrementCount}/>
            </div>
        );
    }
}

const SibOne = props => <div>Count: {props.count}</div>;

const SibTwo = props => (
    <button onClick = {props.incrementCount}>
        Increment Count
    </button>
);

Демо: https://codesandbox.io/s/zqp9wj2n63

Подробнее о Компоненты и реквизит: https://reactjs.org/docs/components-and-props.html

Шина событий - это только регистр глобальной функции, можете ли вы его использовать?

class _EventBus {

    constructor() {
        this.bus = {};
    }

    $off(id) {
       delete this.bus[id];
    }

    $on(id, callback) {
        this.bus[id] = callback;
    }

    $emit(id, ...params) {
        if (this.bus[id])
            this.bus[id](...params);
    }
}

export const EventBus = new _EventBus();

export const предотвращает множественные экземпляры, делая класс статическим.

Ответы только на код не приветствуются. Пожалуйста, объясните, как это решает проблему или чем это отличается от существующих ответов. Из обзора

Nick 07.09.2019 08:04

rxjs - еще один вариант, который вы можете изучить. проверьте, может ли это помочь вам, поскольку они предоставляют наблюдаемые и основанные на событиях программы. Он также делает то же самое, что и Eventbus в vuejs.

Для тех, кто все еще ищет, посмотрите эту статью: https://www.pluralsight.com/guides/how-to-communicate-between-independent-components-in-reactjs

В решении используются:

document.addEventListener для $on;

document.dispatchEvent для $emit;

document.removeEventListener для $off;

В моем случае использования у меня был компонент, содержащий кнопку «Обновить», которая запускала обновление данных в других компонентах.

Все сделал так, как было написано в статье. Если вы используете React с функциональными компонентами, вы можете использовать следующий useEffect:

  useEffect(() => {
    // The component might unmount when the request is in progress.
    // Because of this an error will appear when we'll try to 'setData'.
    let isMounted = true

    const getData = () => {
      reqData(db, path)
        .then(result => {
          if (isMounted) {
            setData(result) // This is a useState
          }
        })
    }

    eventBus.on('refreshData', (data) => {
      getData()
    })

    getData()

    return () => {
      isMounted = false
      eventBus.remove('refreshData')
    }

    // Do not change the end of this useEffect. Keep it as it is. It simulates componentDidMount.
    // eslint-disable-next-line
  }, [])

Другие вопросы по теме