React onClick срабатывает несколько раз при загрузке и не содержит функцию обратного вызова в реквизите компонента

Я считаю, что у меня есть две основные проблемы, которые, вероятно, связаны. Я пытаюсь поместить обработчик событий с функцией обратного вызова на вложенный компонент. Он, казалось, ничего не делал, поэтому я заменил функцию обратного вызова на оповещениеJSON.stringify(this.props), чтобы увидеть, если это прольет свет. Это осветило две проблемы: 1) моя функция обратного вызова не была в реквизите. 2) предупреждение выскочил 2 раза при загрузке страницы, но не выскочил на щелчок, как это должно было быть. Я работаю с этим учебником React . Вот соответствующие компоненты:

var App = React.createClass({
  mixins: [Catalyst.LinkedStateMixin],
  getInitialState: function(){
    return {
      fishes: {},
      order: {}
    }
  },
  componentDidMount: function(){
    base.syncState(this.props.params.storeId + '/fishes', {
      context: this,
      state: 'fishes'
    });
    var localStorageRef = localStorage.getItem('order-' + this.props.params.storeId);
    if(localStorageRef){
      this.setState({
        order: JSON.parse(localStorageRef)
      });
    }
  },
  componentWillUpdate: function(nextProps, nextState){
    localStorage.setItem('order-' + this.props.params.storeId, JSON.stringify(nextState.order));
  },
  loadSamples: function(){
    this.setState({
      fishes: require('./sample-fishes.js')
    });
  },
  addFish: function(fish){
    var timestamp = (new Date()).getTime();
    this.state.fishes['fish-' + timestamp] = fish;
    this.setState({ fishes: this.state.fishes });
  },
  removeFish: function(key){
    if(confirm("Are you sure you want to remove this fish?")){
      this.state.fishes[key] = null;
      this.setState({ fishes: this.state.fishes });
    }
  },
  addToOrder: function(key){
    this.state.order[key] = this.state.order[key] + 1 || 1;
    this.setState({ order: this.state.order });
  },
// <<<<<<<< the function I'm having trouble with >>>>>>>>
  removeFromOrder: function(key){  
    alert('hi');
    delete this.state.order[key];
    this.setState({ order: this.state.order });
  },
  renderFish(key){
    return <Fish key={key} index={key} details={this.state.fishes[key]} addToOrder={this.addToOrder}/>
  },
  render: function(){
    return (
      <div className="catch-of-the-day">
        <div className="menu">
          <Header tagline="Fresh Seafood Market"/>
          <ul className="list-of-fish">
            {/*{ Object.keys(this.state.fishes).map(this.renderFish) }*/}
            { Object.keys(this.state.fishes).length > 0 ? Object.keys(this.state.fishes).map(this.renderFish) : <li>No Fishes!</li> }
          </ul>
        </div>
// <<<<<<<< I pass the function through to the Order component >>>>>>>>
        <Order fishes={this.state.fishes} order={this.state.order} removeFromOrder={this.removeFromOrder}/>
        <Inventory fishes={this.state.fishes} addFish={this.addFish} removeFish={this.removeFish} loadSamples={this.loadSamples} linkState={this.linkState}/>
      </div>
    )
  }
});

var Order = React.createClass({
  renderOrder: function(key){
    var fish = this.props.fishes[key];
    var count = this.props.order[key];
// <<<<<<<< the onClick I'm having trouble with >>>>>>>>
    var removeButton = <button onCLick={this.props.removeFromOrder.bind(null, key)}>&times;</button>
    // var removeButton = <button onCLick={alert(JSON.stringify(this.props))}>&times;</button>
    if(!fish) {
      return <li key={key}>Sorry, that fish is no longer available! {removeButton}</li>
      // return <li key={key}>Sorry, that fish is no longer available!</li>
    }
    return (
      <li key={key}>
        {count}lbs
        {" " + fish.name}
        <span className="price">{helpers.formatPrice(count * fish.price)} {removeButton}</span>
        {/*<span className="price">{helpers.formatPrice(count * fish.price)}</span>*/}
      </li>
    )
  },
  render: function(){
    var orderIds = Object.keys(this.props.order);
    var total = orderIds.reduce((prevTotal, key)=>{
      var fish = this.props.fishes[key];
      var count = this.props.order[key];
      var isAvailable = fish && fish.status === 'available';
      if(isAvailable) {
        return prevTotal + (count * parseInt(fish.price) || 0);
      }
      return prevTotal;
    }, 0);
    return (
      <div className="order-wrap">
        <h2 className="order-title">Your Order</h2>
        <ul className="order">
          { orderIds.length > 0 ? orderIds.map(this.renderOrder) : ""}
          <li className="total">
            <strong>Total:</strong>
            {helpers.formatPrice(total)}
          </li>
        </ul>
      </div>
    )
  }
});

Реквизит для заказа должен включать: доступные рыбы со всеми их деталями, текущий заказ с идентификатором рыбы и количеством, и обратный вызов removeFromOrder. Когда я исследую компонент в React dev tools, у него есть все эти вещи.

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

На потенциально связанной заметке, Когда я исследую компонент в React dev tools и наведу указатель мыши на элемент списка в порядке, я получу следующую ошибку: TypeError: node.getBoundingClientRect is not a function. Я не уверен, является ли это частью моей проблемы; если это не так, я не слишком беспокоюсь об этом, так как это только кажется, всплывает, когда я наведу курсор на элемент в инструментах разработки.

Спасибо за чтение этой длинной вещи, и любая помощь была бы очень благодарна!

1 ответ

  1. Как отметил @azium, проблема заключалась в простой опечатке: onCLick={alert()}вместо onClick={alert()}. Фейспалмить.