【问题标题】:React Native components not rendering inside map() iteratorReact Native 组件不在 map() 迭代器中渲染
【发布时间】:2018-07-21 20:33:42
【问题描述】:

我在下面有一个方法来遍历对象并渲染组件。下面的方法按预期工作。

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

【问题讨论】:

  • 我认为这可能与添加绑定(this)有关。

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


【解决方案1】:

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

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

而在您更新的方法中,您在 Object.values(mealList).map(meal =&gt; { ... }) 语句之前缺少了 return 关键字。

【讨论】:

  • 这是正确的谢谢。如果可以的话,我会在几分钟内接受并粘贴代码解决方案。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多