尝试添加以从api调用获取信息到我的后端

时间:2019-04-04 23:03:45

标签: node.js reactjs react-redux axios

渲染列表后,我从第三方API获得了食谱列表。当我按下“收藏夹”按钮时,我想将特定的添加到收藏夹列表中。但是,每当我尝试呈现配方列表时,我都会收到错误消息“ TypeError:无法读取未定义的属性'addtoFavorites'”

任何帮助将不胜感激。

当我删除“ onClick = {this.addtoFavorites.bind(this)}”时,组件将按预期方式呈现。我不知道为什么addtoFavorites未定义

class RecipeList extends Component {

addtoFavorites = (ev) => {
      const val = ev.target.dataset.value;
      this.props.recipeToFavorite(val);
      console.log(val)  

renderRecipe(recipeData) {
    let recipeName = recipeData.recipeName;
    let recipeId = recipeData.id;
    let recipeIngredients = recipeData.ingredients.join(", ");
    let recipeURL = "https://www.yummly.com/recipe/" + recipeData.id;
    let recipeImage = recipeData.smallImageUrls;
    var recipeDataObj = { name:recipeName, recipeID:recipeId, recipeImage:recipeImage, recipeURL: recipeURL }
  }

    return (
      <div>
      <div key={recipeData.id}>
              <div>
                <img
                  src= {recipeImage}
                  alt="FoodPic"
                />
                <h4> {recipeName} </h4>
                <div>
                  <h3>Ingredients</h3>
                </div>
                <ul>
                  {recipeIngredients}
                </ul>
                <h6>
                  <a href={recipeURL}>
                    Recipe
                  </a>
                </h6>
              </div>
            </div>
            <button
              onClick={this.addtoFavorites.bind(this)}
              data-value={recipeDataObj}
            >
              Fav
            </button>
          </div>
          );
  }
  render() {
    return (
      <div>
        <h2 className="">Recipes</h2>
        <div className="">{this.props.recipes.map(this.renderRecipe)}</div>
      </div>
    );
  }
}

function mapStateToProps({ recipes }) {
//console.log("List Recipes", recipes)
  return {
    recipes
  };
}
export default connect(mapStateToProps)(RecipeList);

import _ from "lodash";
import React, { Component } from "react";
import { compose } from "redux";
import { connect } from "react-redux";
import * as actions from "../Actions";

class FoodList extends Component {
  componentDidMount() {
    this.props.fetchFoodList();
  }

  addIngredientToPot = ev => {
    const val = ev.target.dataset.value;
    this.props.addToPot(val);
  };

  onDeleteClick = ev => {
    const val = ev.target.dataset.value;
    this.props.deleteFood(val);
    this.props.fetchFoodList();
  };

  displayFoodList() {
    return _.map(this.props.foods, food => {
      return (
        <tr key={food._id}>
          <td
            onClick={this.addIngredientToPot.bind(this)}
            data-value={food.name}
          >
            {food.name}
          </td>
          <td>{food.type}</td>
          <td>{food.count}</td>
          <td>{food.created_at}</td>
          <td>
            <button
              data-value={food._id}
              onClick={this.onDeleteClick.bind(this)}
            >
              Throw Out
            </button>
          </td>
        </tr>
      );
    });
  }
  render() {
    return (
      <div>
        <div>
          <div>
            <div />
          </div>
          <div>
            <div>
              <table>
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Type</th>
                    <th>Count</th>
                    <th>Date Added</th>
                    <th>Throw Out</th>
                  </tr>
                </thead>
                <tbody>{this.displayFoodList()}</tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    foods: state.foods,
    pot: state.pot
  };
}
export default compose(
  connect(
    mapStateToProps,
    actions
  )
)(FoodList);

2 个答案:

答案 0 :(得分:0)

尝试将 addtoFavorites 方法更改为常规函数,而不是像这样的箭头函数。

class RecipeList extends Component {

constructor() {
  this.addtoFavorites = this.addtoFavorites.bind(this);
}

addtoFavorites (ev){
      const val = ev.target.dataset.value;
      this.props.recipeToFavorite(val);
      console.log(val)  
}

renderRecipe(recipeData) {
    let recipeName = recipeData.recipeName;
    let recipeId = recipeData.id;
    let recipeIngredients = recipeData.ingredients.join(", ");
    let recipeURL = "https://www.yummly.com/recipe/" + recipeData.id;
    let recipeImage = recipeData.smallImageUrls;
    var recipeDataObj = { name:recipeName, recipeID:recipeId, recipeImage:recipeImage, recipeURL: recipeURL }
  }

    return (
      <div>
      <div key={recipeData.id}>
              <div>
                <img
                  src= {recipeImage}
                  alt="FoodPic"
                />
                <h4> {recipeName} </h4>
                <div>
                  <h3>Ingredients</h3>
                </div>
                <ul>
                  {recipeIngredients}
                </ul>
                <h6>
                  <a href={recipeURL}>
                    Recipe
                  </a>
                </h6>
              </div>
            </div>
            <button
              onClick={this.addtoFavorites}
              data-value={recipeDataObj}
            >
              Fav
            </button>
          </div>
          );
  }
  render() {
    return (
      <div>
        <h2 className="">Recipes</h2>
        <div className="">{this.props.recipes.map(this.renderRecipe)}</div>
      </div>
    );
  }
}

function mapStateToProps({ recipes }) {
//console.log("List Recipes", recipes)
  return {
    recipes
  };
}
export default connect(mapStateToProps)(RecipeList);

答案 1 :(得分:0)

如果您从文档中阅读了主要概念,则在handling events下对此进行了说明。

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default。了解有关在MDN上自动装箱的更多信息

arrow functions也没有自己 this。 (MDN)因此,当您执行this.addtoFavorites.bind(this)时,没有this要绑定。

所以处理事件的可能方法(根据文档):

将处理程序定义为常规javascript函数并绑定到构造函数中,因此在您情况下

constructor(props) {
  // This binding is necessary to make `this` work in the callback
  this.addtoFavorites = this.addtoFavorites.bind(this);
}

function addtoFavorites (ev) {

使用实验性的公共类字段语法,您可以使用类字段正确地绑定回调(不确定这是否仍处于实验性):

// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
addtoFavorites = (ev) => {
  ...

在回调中使用箭头功能

addtoFavorites = (ev) => {

onClick={(e) => this.addtoFavorites(e)}

但是请注意,如果您使用此解决方案(来自docs):此语法的问题是,每次LoggingButton呈现时都会创建一个不同的回调。在大多数情况下,这很好。但是,如果将此回调作为对较低组件的支持传递,则这些组件可能会进行额外的重新渲染。

React的建议是使用binding解决方案。

我们通常建议在构造函数中进行绑定或使用类字段语法进行绑定,以避免此类性能问题。