React onClick 在加载时多次触发,并且组件道具中不包含回调函数

React onClick fires multiple times on load and doesn't contain callback function in component props

我相信我有两个基本问题,它们可能是相关联的。我试图在嵌套组件上放置一个带有回调函数的事件处理程序。它似乎没有做任何事情,所以我用 JSON.stringify(this.props) 的警报替换了回调函数,看看这是否会有所帮助。它说明了两个问题:1)我的回调函数不在道具中。 2) 警报在页面加载时弹出 2 次,但没有像预期的那样在点击时弹出。我正在处理 this React tutorial。以下是相关组件:

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>
    )
  }
});

Order 的属性应该包括:可用的鱼及其所有详细信息、带有鱼 ID 和数量的当前订单以及 removeFromOrder 回调。当我探索 React 开发工具中的组件时,它拥有所有这些东西。

当我用道具警报替换 removeFromOrder 回调时,会发生什么: - 点击,什么都没有 - 在页面刷新时,弹出两个警告:第一个提示包括当前订单和一个空的 fishes 数组,第二个提示包括当前订单和已填充的 fishes 数组。两者都没有显示 removeFromOrder 回调函数,从事件侦听器的角度来看,它似乎是未定义的。

关于一个可能相关的说明,当我在 React 开发工具中浏览组件并将鼠标悬停在订单中的列表项上时,我收到以下错误:TypeError: node.getBoundingClientRect is not a function。我不确定这是否是我问题的一部分;如果不是,我不太关心它,因为它似乎只在我将鼠标悬停在开发工具中的元素上时才会弹出。

感谢您阅读这篇长文,如有任何帮助,我们将不胜感激!

正如@azium 指出的那样,问题是一个简单的错字:onCLick={alert()} 应该是 onClick={() => alert()}。捂脸。