web-dev-qa-db-fra.com

react.js événements personnalisés pour communiquer avec les nœuds parents

Je suis en train d'écouter et de faire en sorte que les DOMCustomEvents normaux communiquent avec les nœuds parents:

Chez l'enfant:

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

En parent:

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

Cela fonctionne, mais y a-t-il une manière spécifique à React qui serait meilleure?

65
forresto

Comme indiqué ci-dessus:

La méthode React consisterait à transmettre explicitement les rappels aux enfants via des accessoires -. Les événements personnalisés ne sont pas pris en charge dans React.

L'abstraction de programmation réactive est orthogonale:

La programmation de systèmes interactifs à l'aide du modèle d'observateur est difficile et sujette aux erreurs, mais elle reste la norme d'implémentation dans de nombreux environnements de production. Nous présentons une approche visant à déprécier progressivement les observateurs en faveur des abstractions de programmation réactive. Plusieurs couches de bibliothèque aident les programmeurs à migrer en douceur le code existant des rappels vers un modèle de programmation plus déclaratif.

La philosophie React est basée sur le modèle de commande:

enter image description here

Références

37
Paul Sweatte

vous pouvez écrire un service simple puis l'utiliser

/** 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];
  },
};

exemple (idem pour le déclenchement)

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');
  }
}
4
Dr.Tranquility

J’en ai trouvé un autre qui est tout à fait raisonnable aussi, surtout si le forage d’un parent à l’enfant devient déjà fastidieux. Il a appelé la communication moins simple. Voici le lien:

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

3
index

Vous pouvez faire remonter des événements par le biais de rappels transmis via des contextes: [CodePen]

import * as React from 'react';

const MyEventContext = React.createContext(() => {});

const MyEventBubbleContext = ({children, onMyEvent}) => {
  const bubbleEvent = React.useContext(MyEventContext);
  const handleMyEvent = React.useCallback((...args) => {
    // stop propagation if handler returns false
    if (onMyEvent(...args) !== false) {
      // bubble the event
      bubbleEvent(...args);
    }
  }, [onMyEvent]);
  return (
    <MyEventContext.Provider value={handleMyEvent}>
      {children}
    </MyEventContext.Provider>
  );
};

const MyComponent = () => (
  <MyEventBubbleContext onMyEvent={e => console.log('grandparent got event: ', e)}>
    <MyEventBubbleContext onMyEvent={e => console.log('parent got event: ', e)}>
      <MyEventContext.Consumer>
        {onMyEvent => <button onClick={onMyEvent}>Click me</button>}
      </MyEventContext.Consumer>
    </MyEventBubbleContext>
  </MyEventBubbleContext>
);

export default MyComponent;
2
Andy

Une solution possible, si vous devez absolument recourir au modèle Observer dans une application ReactJs, vous pouvez détourner un événement normal. Par exemple, si vous souhaitez que la touche Suppr provoque un <div> Marqué pour suppression, vous pouvez demander à <div> D'écouter un événement de raccourci appelé par un événement personnalisé. Intercepter la keydown sur le corps et envoyer un événement customEvent sur le <div> Sélectionné. Partage au cas où cela aiderait quelqu'un.

2
Doug

Un magasin central [Redux] qui distribue l'état aux clients, puis l'état de "répartition" vers le magasin ressemblent également à un modèle d'observateur. Une façon de faire publier/souscrire est encore pire en raison de la surcharge explicite (fragile?) Reliant les chemins accessoires/événements. Pour pirater la hiérarchie React fournit un contexte (modèle de fournisseur) ou des bibliothèques observables qui pue. Comme MobX qui introduit de nouveaux décorateurs @observable, ou Vue qui introduit de nouveaux La syntaxe de gabarit "v-if". Les événements sont le moyen principal de fonctionnement de la boucle d'événements DOM et javascript, alors pourquoi pas? Je pense que les satanistes l'ont fait. Lol

1
user982671

Je me rends compte que cette question est assez ancienne maintenant, mais cette réponse pourrait toujours aider quelqu'un. J'ai écrit un pragma JSX pour React) qui ajoute un événement personnalisé déclaratif: jsx-native-events .

Fondamentalement, vous utilisez simplement le onEvent<EventName> modèle à surveiller pour les événements.

<some-custom-element onEventSomeEvent={ callback }></some-custom-element>
0
Caleb Williams