Pregunta

Estoy teniendo problemas para conseguir los elementos de menú conectado a un controlador de eventos.Aquí está una maqueta de la interfaz de usuario que muestra los cambios de estado a lo largo del tiempo.Es un menú desplegable (a través de Bootstrap), con la raíz del elemento de menú que muestra la selección actual:

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

El objetivo final es cambiar el contenido de la página de forma asincrónica basada en la selección del usuario.Haciendo click sobre Bob debe desencadenar la handleClick, pero no lo es.

Como una nota del lado, no estoy terriblemente contento con la forma en componentDidMount llamadas this.handleClick();, pero por ahora funciona como una forma de obtener inicial del menú de contenido desde el servidor.

/** @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')
  );
});

Estoy casi segura de que mi nublada comprensión de javascript alcance tiene la culpa, pero todo lo que he probado hasta ahora ha fallado (incluyendo tratando de pasar el controlador de abajo a través de los apoyos).

¿Fue útil?

Solución

El problema es que va a crear el elemento de nodos mediante una función anónima, y dentro de ese this significa que el window.La solución es agregar .bind(this) a la función anónima.

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

O crear una copia de this y utilizar en su lugar:

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

Otros consejos

Como puedo entender la especificación de la tarea de "Anna", "Bob", "Cal, la solución puede ser la siguiente (basado en un reaccionan componente y ES6):

Básico de demostración en vivo está aquí

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>
    )
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top