Question

J'ai du mal à connecter les éléments de menu à un gestionnaire d'événements.Voici une maquette de l'interface utilisateur montrant les changements d'état au fil du temps.Il s'agit d'un menu déroulant (via Bootstrap), avec l'élément de menu racine affichant la sélection actuelle :

[ANN]<click  ...  [ANN]             ...    [BOB]<click  ...  [BOB]  
                    [Ann]                                      [Ann]
                    [Bob]<click + ajax                         [Bob]
                    [Cal]                                      [Cal]

L'objectif final est de modifier le contenu de la page de manière asynchrone en fonction de la sélection de l'utilisateur.Cliquer sur Bob devrait déclencher le handleClick, mais ce n'est pas.

En passant, je ne suis pas très satisfait de la façon dont ComponentDidMount appelle this.handleClick();, mais cela fonctionne pour l'instant comme un moyen d'obtenir le contenu du menu initial du serveur.

/** @jsx React.DOM */

var CurrentSelection = React.createClass({
  componentDidMount: function() {
    this.handleClick();
  },

  handleClick: function(event) {
    alert('clicked');
    // Ajax details ommitted since we never get here via onClick
  },
  getInitialState: function() {
    return {title: "Loading items...", items: []};
  },
  render: function() {
    var itemNodes = this.state.items.map(function (item) {
      return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
    });

    return <ul className='nav'>
      <li className='dropdown'>
        <a href='#' className='dropdown-toggle' data-toggle='dropdown'>{this.state.title}</a>
        <ul className='dropdown-menu'>{itemNodes}</ul>
      </li>
    </ul>;
  }
});


$(document).ready(function() {
  React.renderComponent(
    CurrentSelection(),
    document.getElementById('item-selection')
  );
});

Je suis presque sûr que ma compréhension floue de la portée de Javascript est à blâmer, mais tout ce que j'ai essayé jusqu'à présent a échoué (y compris essayer de transmettre le gestionnaire via les accessoires).

Était-ce utile?

La solution

Le problème est que vous créez les nœuds d'élément à l'aide d'une fonction anonyme, et à l'intérieur de celle-ci this signifie le window.Le correctif consiste à ajouter .bind(this) à la fonction anonyme.

var itemNodes = this.state.items.map(function (item) {
  return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
}.bind(this));

Ou créez une copie de this et utilisez-le à la place :

var _this = this, itemNodes = this.state.items.map(function (item) {
  return <li key={item}><a href='#' onClick={_this.handleClick}>{item}</a></li>;
})

Autres conseils

Si je peux comprendre la spécification de la tâche pour "Anna", "Bob", "Cal, la solution peut être la suivante (basée sur un composant React et ES6) :

La démo live de base est ici

import React, { Component } from "react"

export default class CurrentSelection extends Component {
  constructor() {
    super()
    this.state = {
      index: 0
    }
    this.list = ["Anna", "Bob", "Cal"]
  }

  listLi = list => {
    return list.map((item, index) => (
      <li key={index}>
        <a
          name={item}
          href="#"
          onClick={e => this.onEvent(e, index)}
        >
          {item}
        </a>
      </li>
    ))
  }

  onEvent = (e, index) => {
    console.info("CurrentSelection->onEvent()", { [e.target.name]: index })
    this.setState({ index })
  }

  getCurrentSelection = () => {
    const { index } = this.state
    return this.list[index]
  }

  render() {
    return (
      <div>
        <ul>{this.listLi(this.list)}</ul>
        <div>{this.getCurrentSelection()}</div>
      </div>
    )
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top