Вопрос по reactjs – реагировать на события с родительскими узлами

59

Я делаю и слушаю нормальный DOMCustomEvents для связи с родительскими узлами:

У ребенка:

  var moveEvent = new CustomEvent('the-graph-group-move', { 
    detail: {
      nodes: this.props.nodes,
      x: deltaX,
      y: deltaY
    },
    bubbles: true
  });
  this.getDOMNode().dispatchEvent(moveEvent);

В родительском:

componentDidMount: function () {
  this.getDOMNode().addEventListener("the-graph-group-move", this.moveGroup);
},

Это работает, но есть ли специфичный для React способ, который был бы лучше?

Обожая MVVM от Microsoft в WPF, это было естественным, что я ожидал от React - вместо того, чтобы либо передавать обратный вызов через иерархию компонентов, которые не заботятся об этом, либо иметь одного всемогущего единственного диспетчера (который пахнет плохим дизайном на многие мили) , Это может быть неподдерживаемый сценарий, но я все еще попробую, как далеко он сможет меня достать :). Tomáš Kafka
Я не был саркастичным. forresto
Таким образом, пузырьки обратного вызова вниз вместо событий вверх? Кажется разумным. forresto
@ TomášKafka Я согласен, я думаю, именно поэтому многие из нас хотят, чтобы наши собственные пользовательские события всплыли так, чтобы их могли обрабатывать неглобальные не-одиночные диспетчеры на каком-либо родительском уровне. Передача обратных вызовов является вполне жизнеспособным шаблоном, но для передачи их через каждый уровень требуется больше стандартного кода, чем для всплытия событий, и требуется только добавить код для обработки их на уровне (уровнях), которые действительно что-то делают с событиями. Andy

Ваш Ответ

6   ответов
1

Возможное решение, если вы абсолютнодолжен прибегнув к шаблону Observer в приложении ReactJs, вы можете захватить обычное событие. Например, если вы хотите, чтобы ключ удаления вызывал<div> помеченный для удаления, вы можете иметь<div> прослушать событие keydown, которое будет вызвано customEvent. Лови ключ на теле и отправьcustomEvent событие keydown на выбранном<div>, Обмен в случае, если это кому-то помогает.

33

Как указано выше:

Способом React было бы передать обратные вызовы детям в явном виде через реквизиты -. Там нет поддержки пользовательских событий с пузырьками в React.

Реакционная абстракция программирования ортогональна:

Программирование интерактивных систем с помощью шаблона наблюдателя является сложным и подверженным ошибкам, но все еще остается стандартом реализации во многих производственных средах. Мы представляем подход к постепенному осуждению наблюдателей в пользу абстракций реактивного программирования. Несколько уровней библиотеки помогают программистам плавно переносить существующий код из обратных вызовов в более декларативную модель программирования.

Философия React основана на шаблоне Command:

Рекомендации

Устаревая шаблон наблюдателяШаблон команды: История командВзаимодействие компонентов с элементами React и CustomСборка Redux в TypeScriptЧем Мифрил отличается от других рамок - Мифрил
Меня интересует, почему в React нет поддержки пользовательских синтетических событий. Это просто, что они никогда не были реализованы, или есть правильное проектное решение, почему они не были? Считаются ли события вредными, как заявления goto? Michael Bylstra
Принимая во внимание тот факт, что компоненты взаимодействуют с хранилищем данных, введенным предком через контекст React (Redux, React Router и т. Д. Все используют контекст), совершенно неестественно говорить, что дочерний процесс, вызывающий обратно предку через какую-либо функцию в контексте, не является идиоматическая Реакция. Нет реальной разницы между вызовом Redux «dispatch» с объектом «action» и вызовом «обработчика события» в контексте с объектом «event». Andy
Длинные цепочки событий, запускающие другие события, довольно часто встречаются в том, как некоторые люди используют Redux (например, безумие из-за избыточной саги) Andy
@MichaelBylstra Пользовательские события осуждаются из-заклассический выпуск: a class of debugging problems where you don't know what triggers some code because of a long chain of events triggering other events,шаблон команд содносторонний поток данных Реактивная философия. Paul Sweatte
3

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

https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/04-less-simple-communication.md

Это в основном говорит "реализовать шаблон наблюдателя". Я согласен с комментарием Майкла Билстры относительно ОП, описывающим проблему, отмеченную в «Менее простом сообщении», как «сверление дыр» ... без пузырей, передача обратных вызовов не обрабатывает структуры глубиной более 1 уровня. ericsoco
Эта статья выглядит так, как будто она заново изобретает (изобретает?) Redux:redux.js.org Austin Hyde
3

Вы можете написать простой сервис, а затем использовать его

/** eventsService */
module.exports = {
  callbacks: {},

  /**
   * @param {string} eventName
   * @param {*} data
   */
  triggerEvent(eventName, data = null) {
    if (this.callbacks[eventName]) {
      Object.keys(this.callbacks[eventName]).forEach((id) => {
        this.callbacks[eventName][id](data);
      });
    }
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   * @param {Function} callback
   */
  listenEvent(eventName, id, callback) {
    this.callbacks[eventName][id] = callback;
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   */
  unlistenEvent(eventName, id) {
    delete this.callbacks[eventName][id];
  },
};

пример (то же самое для запуска)

import eventsService from '../../../../services/events';
export default class FooterMenu extends Component {
  componentWillMount() {
    eventsService
      .listenEvent('cart', 'footer', this.cartUpdatedListener.bind(this));
  }

  componentWillUnmount() {
    eventsService
      .unlistenEvent('cart', 'footer');
  }

  cartUpdatedListener() {
    console.log('cart updated');
  }
}
1

Вы можете всплывать события через обратные вызовы, передаваемые через контексты:[CodePen]

import React, {Component, PropTypes} from 'react';

class EventContext extends Component {
  static contextTypes = {
    onMyEvent: PropTypes.func
  };
  static childContextTypes = {
    onMyEvent: PropTypes.func.isRequired
  };
  static propTypes = {
    onMyEvent: PropTypes.func.isRequired
  };
  getChildContext() {
    let {onMyEvent} = this.props;
    return {
      onMyEvent: (...args) => {
        // stop propagation if handler returns false
        if (onMyEvent(...args) !== false) {
          // bubble the event
          this.context.onMyEvent && this.context.onMyEvent(...args);
        }
      }
    };
  }
  render() {
    return this.props.children;
  }
}

class MyComponent extends Component {
  static contextTypes = {
    onMyEvent: PropTypes.func
  };
  render() {
    let {onMyEvent} = this.context;
    return <button onClick={onMyEvent}>Click me</button>;
  }
}

export default <EventContext onMyEvent={e => console.log('grandparent got event: ', e)}>
  <EventContext onMyEvent={e => console.log('parent got event: ', e)}>
    <MyComponent/>
  </EventContext>
</EventContext>;
1

Центральное хранилище [Redux], которое распределяет состояние по клиентам, которое затем «отправляет» состояние обратно в хранилище, похоже на шаблон наблюдателя. Способ делать публикацию / подписку только хуже из-за явных (хрупких?) Накладных расходов, соединяющих пути реквизитов / событий. Чтобы разобраться в иерархии, React предоставляет контекст (шаблон поставщика) или наблюдаемые библиотеки, которые воняют. Как MobX, который вводит новые декораторы @observable, или Vue, который вводит новый синтаксис шаблона "v-if". События в любом случае являются основным способом работы цикла событий DOM и javascript, так почему бы и нет? Я думаю, что сатанисты сделали это. Лол

Похожие вопросы