React Native组件不在map()迭代器中呈现

时间:2018-02-11 16:06:22

标签: javascript reactjs react-native ecmascript-6 es6-modules

我有一个方法来迭代一个对象并渲染组件。以下方法按预期工作。

  renderListOfMeals() {
    if (this.props.mealPlan !== undefined) {
      return (
        Object.values(this.props.mealPlan).map(meal =>
          <Meal key={meal.id} meal={meal} />
      )
    );
    }
}

我想更新方法,根据是否已添加到收藏夹,返回稍微不同版本的Meal组件。下面的方法返回正确的组件,但它们不会在屏幕上呈现,我无法弄清楚原因。

  renderListOfMeals() {
    const { mealList, favourited } = this.props;

    if (mealList !== undefined) {
        Object.values(mealList).map(meal => {
          if (Object.prototype.hasOwnProperty.call(favourited, meal.id)) {
            return <Meal key={meal.id} meal={meal} favourited />;
          }
            return <Meal key={meal.id} meal={meal} favourited={false} />;
        });
      }
    }

以下是完整的课程供参考:

ListOfMeals.js

import React, { Component } from 'react';
import { View } from 'react-native';
import Meal from './Meal';

class ListOfMeals extends Component {
  /* Props
  * mealList: List of meal objects to be rendered
  * favourited: List of meals that are already favourited
  */


  renderListOfMeals() {
    const { mealList, favourited } = this.props;

    if (mealList !== undefined) {
        Object.values(mealList).map(meal => {
          if (Object.prototype.hasOwnProperty.call(favourited, meal.id)) {
            return <Meal key={meal.id} meal={meal} favourited />;
          }
            return <Meal key={meal.id} meal={meal} favourited={false} />;
        });
      }
    }

  render() {
    return (
      <View>
        {this.renderListOfMeals()}
      </View>
    );
  }

}

export default ListOfMeals;

Meal.js

import React, { Component } from 'react';
import firebase from 'firebase';
import { View, Text } from 'react-native';
import { Actions } from 'react-native-router-flux';
import axios from 'axios';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import Config from '../../Config';
import { Card, CardSection, LoadingOverlay } from '../common';
import FoodRow from './FoodRow';
import { ActionButton } from './ActionButton';

class Meal extends Component {
  // Redux not needed here as no major state, only booleans used to alter rendering.. //
  state = { liked: false, favourited: false, loading: false };

    componentWillMount() {
      if (this.props.favourited) {
        this.setState({ favourited: true });
      }
    }

    getSimiliarMeals() {
      const mealId = this.props.meal.id;
      this.setState({ loading: true });
        axios.get(`${Config.BASE_URL}/meal/${mealId}/similar`)
        .then(response => {
          this.setState({ loading: false });
          Actions.ListOfMeals({ mealList: response.data });
        })
        .catch(this.setState({ loading: true }));
    }

    likeMeal() {
        const { currentUser } = firebase.auth();
        const mealId = this.props.meal.id;
        this.setState({ loading: true });
          axios.post(`${Config.BASE_URL}/meal/${mealId}/like`, currentUser.uid)
          .then(response => {
            this.setState({ loading: false });
            this.setState({ liked: response.data });
          })
          .catch(this.setState({ loading: false }));
      }

    favOrUnfavMeal() {
      const { currentUser } = firebase.auth();
      const meal = this.props.meal;
      this.setState({ loading: true });

      if (this.state.favourited) {
        firebase.database().ref(`users/${currentUser.uid}/favouritedMeals/${meal.id}`)
        .set(null)
        .then(response => {
          this.setState({ loading: false });
          this.setState({ favourited: false });
      })
      .catch(this.setState({ loading: false }));
    } else {
      firebase.database().ref(`users/${currentUser.uid}/favouritedMeals/${meal.id}`)
      .set(meal)
      .then(response => {
        this.setState({ loading: false });
        this.setState({ favourited: true });
      })
      .catch(this.setState({ loading: false }));
    }
  }

    renderFoodRows() {
      return (
        Object.values(this.props.meal.mealFoods).map(food =>
          <FoodRow key={food.id} food={food} />
      )
    );
  }

  renderLike() {
    if (!this.state.liked) return <Icon name='thumb-up-outline' size={20} color='green' />;
  }

  renderFavouriteOrUnfavourite() {
    if (this.state.favourited) return <Icon name='heart' size={20} color='red' />;
      return <Icon name='heart-outline' size={20} />;
  }

  renderSimilarityRating() {
    const { tanimoto } = this.props.meal;
    if (tanimoto !== 0 && tanimoto !== undefined) {
      return (
        <CardSection>
          <Text style={styles.similarityText}>
            {Math.round(Number(tanimoto) * 100)}% also liked
          </Text>
        </CardSection>
      );
    }
  }

  renderLoading() {
    if (this.state.loading) return <LoadingOverlay />;
  }

  render() {
    return (
      <View>
      <Card>

      <CardSection>
        <View>
          <Text style={styles.nameHeader}>{this.props.meal.name}</Text>
        </View>
          <ActionButton onPress={this.likeMeal.bind(this)}>
            {this.renderLike()}
          </ActionButton>
          <ActionButton onPress={this.favOrUnfavMeal.bind(this)}>
            {this.renderFavouriteOrUnfavourite()}
          </ActionButton>
          <ActionButton onPress={this.getSimiliarMeals.bind(this)}>
            <Icon name='find-replace' size={20} color='orange' />
          </ActionButton>
      </CardSection>

        {this.renderSimilarityRating()}
        {this.renderFoodRows()}

        <CardSection>
          <Text style={styles.caloriesHeader}>
            {Math.round(this.props.meal.protein)}g protein
             / {Math.round(this.props.meal.carbs)}g carb
             / {Math.round(this.props.meal.fats)}g fat
          </Text>
        </CardSection>
        <CardSection>
          <Text style={styles.caloriesHeader}>
            {Math.round(this.props.meal.calories)} calories
          </Text>
        </CardSection>

      </Card>
      {this.renderLoading()}
      </View>
    );
  }

}

const styles = {
  nameHeader: {
    fontSize: 16,
    fontWeight: 'bold'
  },
  caloriesHeader: {
    fontSize: 13,
    fontWeight: 'bold'
  },
  similarityText: {
    fontSize: 14.5,
    fontWeight: 'bold',
    color: 'green',
    fontStyle: 'italic'
  }
};

export default Meal;

修改: 正确的代码

  renderListOfMeals() {
    const { mealList, favouritedList } = this.props;

    if (mealList !== undefined) {
      return (
        Object.values(mealList).map(meal => {
          if (favouritedList !== undefined && Object.prototype.hasOwnProperty.call(favouritedList, meal.id)) {
            return <Meal key={meal.id} meal={meal} favourited favouritedList={favouritedList} />;
          }
            return <Meal key={meal.id} meal={meal} favourited={false} favouritedList={favouritedList} />;
        })
      );
      }
    }

1 个答案:

答案 0 :(得分:2)

在原始版本的renderListOfMeals方法中,您有

return (
    Object.values(this.props.mealPlan).map(meal =>
      <Meal key={meal.id} meal={meal} />
  )

在您更新的方法中,您在return声明之前错过了Object.values(mealList).map(meal => { ... })关键字。