我有一个方法来迭代一个对象并渲染组件。以下方法按预期工作。
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} />;
})
);
}
}
答案 0 :(得分:2)
在原始版本的renderListOfMeals
方法中,您有
return (
Object.values(this.props.mealPlan).map(meal =>
<Meal key={meal.id} meal={meal} />
)
在您更新的方法中,您在return
声明之前错过了Object.values(mealList).map(meal => { ... })
关键字。