Reputation: 3692
I'm making a RecipeBox App in React, it works fine until I try to implement a search functionality. The error is thrown as soon as the user enters a search item in the search bar. The else
block in this render
method is what throws the error -
render() {
var gridRecipes = this.props.recipes;
let onDelete = this.props.onRecipeDelete;
//second set of props
let onRecipeNameEdit = this.props.onRecipeNameEdit;
let onRecipeIngEdit = this.props.onRecipeIngredientsEdit;
let onRecipeTagsEdit = this.props.onRecipeTagsEdit;
let onRecipeEditSubmit = this.props.onRecipeEditSubmit;
let onRecipeEditSelect = this.props.onRecipeEditSelect;
let filterNameEdit = this.props.filterNameEdit;
let filterIngredientsEdit = this.props.filterIngredientsEdit;
let filterTagsEdit = this.props.filterTagsEdit;
//props for search
let searchedItem = this.props.searchItem;
console.log(gridRecipes);
var recipeCards = [];
if(searchedItem === "") {
recipeCards = gridRecipes.map(function (recipe, index) {
return <div className="recipe-item" key={index}>
<RecipeCard recipe={recipe} key={index} index={index} onDelete={onDelete}
onRecNameEdit={onRecipeNameEdit}
onRecIngredientsEdit={onRecipeIngEdit}
onRecTagsEdit={onRecipeTagsEdit}
onRecEditSubmit={onRecipeEditSubmit}
filterNameEdit={filterNameEdit}
filterIngredientsEdit={filterIngredientsEdit}
filterTagsEdit={filterTagsEdit}
onRecipeEdit={onRecipeEditSelect}
/>
</div>
});
}
else {
console.log(`user searched for ${searchedItem}`);
recipeCards = gridRecipes.filter(function (recipe, index) {
//console.log(recipe);
if(recipe.name.toLowerCase().indexOf(searchedItem) !== -1) {
return <div className="recipe-item" key={index}>
<RecipeCard recipe={recipe} key={index} index={index} onDelete={onDelete}
filterNameEdit={filterNameEdit}
filterIngredientsEdit={filterIngredientsEdit}
filterTagsEdit={filterTagsEdit}
/>
</div>
}
})
console.log(recipeCards);
console.log(Array.isArray(recipeCards));
}
return (
<div className="flex-container">
{recipeCards}
</div>
)
}
Here's the error message -
Uncaught Error: Objects are not valid as a React child (found: object with keys {name, ingredients, tags}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `RecipeFlexContainer`.
Looking at the error message and reading another similar question, it appears that the collection of children is being rendered as an individual object/collection of objects, as opposed to an array containing the objects. But that is not the case. I've got two
console.log
statements in the code to verify this -
console.log(recipeCards);
console.log(Array.isArray(recipeCards));
The console shows -
[Object]
true
Which shows that recipeCards
is a an array containing object(s). But then the return
throws off the error -
return (
<div className="flex-container">
{recipeCards}
</div>
)
Interestingly, the same return
statement works fine, without throwing any errors, if I remove the search bar functionality and delete the else block entirely -
else {
console.log(`user searched for ${searchedItem}`);
recipeCards = gridRecipes.filter(function (recipe, index) {
//console.log(recipe);
if(recipe.name.toLowerCase().indexOf(searchedItem) !== -1) {
return <div className="recipe-item" key={index}>
<RecipeCard recipe={recipe} key={index} index={index} onDelete={onDelete}
filterNameEdit={filterNameEdit}
filterIngredientsEdit={filterIngredientsEdit}
filterTagsEdit={filterTagsEdit}
/>
</div>
}
})
console.log(recipeCards);
console.log(Array.isArray(recipeCards));
}
Here's my app on Codepen.
Steps to reproduce -
This is in the RecipeFlexContainer
component.
Can anyone explain what's going on?
Upvotes: 3
Views: 1871
Reputation: 16450
Change the filter
to map
and you'll have it fixed:
// after
recipeCards = gridRecipes.map(function (recipe, index) {
// before
recipeCards = gridRecipes.filter(function (recipe, index) {
But a cleaner way would be:
gridRecipes
.filter(r => r.name.toLowerCase().indexOf(searchedItem) !== -1)
.map((r, i) => (
<div className="recipe-item" key={i}>
<RecipeCard />
</div>)
);
Upvotes: 3