Попытка добавить, чтобы получить информацию от вызова API в мой бэкэнд - PullRequest
0 голосов
/ 05 апреля 2019

Я получаю список рецептов от стороннего API после рендеринга списка.Я хочу добавить конкретные в список избранного, когда нажимаю на кнопку Fav.Однако всякий раз, когда я пытаюсь отобразить список рецептов, я получаю сообщение об ошибке «Ошибка типа: невозможно прочитать свойство addtoFoving of undefined»

Любая помощь будет принята с благодарностью.

Когда я удаляю «onClick = {this.addtoFlected.bind (this)}» », компонент рендерится как положено.Я не знаю, почему addtoFoving не определена

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 голосов
/ 06 апреля 2019

Если вы читаете Основные понятия из документов, это объясняется в разделе Обработка событий .

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

Обратите внимание, однако, если вы используете это решение (из документов): Проблема с этим синтаксисом заключается в том, что каждый раз при рендеринге LoggingButton создается другой обратный вызов. В большинстве случаев это нормально. Однако, если этот обратный вызов передается в качестве поддержки более низким компонентам, эти компоненты могут выполнить дополнительный повторный рендеринг.

React рекомендует использовать решение binding.

Мы обычно рекомендуем связывание в конструкторе или использование синтаксиса полей класса, чтобы избежать такого рода проблем с производительностью.

0 голосов
/ 05 апреля 2019

Попробуйте изменить метод addtoFabilities на обычную функцию вместо функции стрелки, подобной этой.

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