3 votes

React transmet tous les événements au composant enfant

Est-il possible dans React de passer tous les événements à l'élément enfant.

à titre d'exemple, j'ai une classe de bouton personnalisée, qui (simplifiée) ressemble à quelque chose comme ceci :

class Button extends Component {

  constructor (props) {
    super(props);

    this.onClick      = this.onClick.bind(this);
  }

  /* .... */

  onClick (ev) {
    const { disabled, onClick } = this.props;
    if (!disabled) {
      onClick(ev);
    }
  }

  render () {
     const {
      children,
      disabled,
      type
     } = this.props;

    return (
      <button
        disabled={disabled}
        onClick={this.onClick}
        ref="button"
        type={type}
      >{children}</button>
  }

}

Je ne sais pas quels événements je pourrais vouloir utiliser à l'avenir (onMouseDown, onMouseUp, onBlur, onKeyDown, onTouchStart, et ainsi de suite...).

Est-il possible de transmettre tous les événements possibles à l'élément button sans écrire un prop pour chaque événement possible ?

L'ajout de {...this.props} à l'élément bouton n'est pas ce que je veux parce qu'il transmet tous les props et que certains props (comme className qui est omis dans cet exemple) ne devraient pas être transmis directement.

J'ai pensé à cloner l'objet props et à supprimer les props qui ne devraient pas être transmis directement, mais cela ressemble à un hack. Quelqu'un connaît-il une méthode plus propre ?

2voto

Barry127 Points 773

J'ai écrit une fonction pour itérer sur les props et filtrer toutes les propriétés commençant par 'on', c'est le plus proche que j'ai fait jusqu'à présent. Au cas où cela aiderait quelqu'un d'autre :

/* helpers.js */

export function filterEvents (props, ignore = []) {
  let events = {};
  for (let property in props) {
    if (props.hasOwnProperty(property)) {
      if (property.startsWith('on') && ignore.indexOf(property) === -1) {
        events[property] = props[property];
      }
    }
  }

  return events;
}

/* Tests for the filterEvents */

import { expect } from 'chai';

import { filterEvents } from './helpers';

describe('filterEvents', () => {

  const props = {
    className: 'someClass',
    disabled: true,
    onBlur: 'onBlur',
    onClick: 'onClick',
    onMouseDown: 'onMouseDown',
    onMouseUp: 'onMouseUp'
  };

  it('only returns keys starting with on', () => {
    const expected = {
      onBlur: 'onBlur',
      onClick: 'onClick',
      onMouseDown: 'onMouseDown',
      onMouseUp: 'onMouseUp'
    };

    expect(filterEvents(props)).to.deep.equal(expected);
  });

  it('only returns keys starting with on minus the ones in the ignore array', () => {
    const expected = {
      onBlur: 'onBlur',
      onMouseUp: 'onMouseUp'
    };

    const ignore = ['onClick', 'onMouseDown'];
    expect(filterEvents(props, ignore)).to.deep.equal(expected);
  });

});

/* Using the function inside a component */

import { filterEvents } from './helpers'; //at the top of the components file

//Inside the render method:

const events = filterEvents(this.props, ['onClick']); //don't include onClick it's handled like the questions example

return (
  <button
    disabled={this.props.disabled}
    onClick={this.onClick}
    {...events}
  >
    {this.props.children}
  </button>
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X