2017-04-27 44 views
1

我在React中制作一个RecipeBox应用程序,它工作正常,直到我尝试实现搜索功能。一旦用户在搜索栏中输入搜索项目,就会抛出错误。在此render方法的else块是什么引发错误 -ReactJS渲染一个孩子的集合抛出“不变的违规:对象不是有效的React子”错误

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

这里的错误信息 -

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`. 

enter image description here 纵观错误信息和阅读another similar question,看来孩子们的集合被渲染为单个对象/对象集合,而不是包含对象的数组。但事实并非如此。我有在两个代码console.log语句来验证这一点 -

console.log(recipeCards); 
console.log(Array.isArray(recipeCards)); 

控制台显示 -

[Object] 
true 

这都说明recipeCards是一个阵列包含的对象(S)。但随后return抛出了错误 -

return (
      <div className="flex-container"> 
       {recipeCards} 
      </div> 
     ) 

有趣的是,同样的return语句工作正常,没有抛出任何错误,如果我删除搜索栏功能,并删除整个else块 -

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

这是我的应用程序Codepen

步骤来重现 -

  1. 在搜索栏中现有配方名称搜索,如“蒜”
  2. 拉起控制台

这是RecipeFlexContainer组件。

任何人都可以解释发生了什么?

+0

所以你要完成的任务是过滤食谱时用户开始输入食谱名称? – bntzio

+0

是的,确切地说。对不起,如果不明确。我只想在他们的名字有用户输入时显示食谱。 –

+0

Sam刚刚回答了你的问题,问题是,你想返回配方并将它保存到'recipeCards'变量中,这就是为什么要使用'map',而不是'filter'。 – bntzio

回答

1

更改filtermap,你就会有它固定的:

// after 
recipeCards = gridRecipes.map(function (recipe, index) { 

// before 
recipeCards = gridRecipes.filter(function (recipe, index) { 

但是更清洁的方法是:

gridRecipes 
    .filter(r => r.name.toLowerCase().indexOf(searchedItem) !== -1) 
    .map((r, i) => (
    <div className="recipe-item" key={i}> 
     <RecipeCard /> 
    </div>) 
); 
+0

是的,这是正确的。 – bntzio

+0

@bntzio @ sam-rad Got it!谢谢!虽然,我不明白为什么使用'.filter()'直接不起作用。我想就像.map()一样,'.filter()'也会返回一个包含通过测试'r.name的元素(在本例中为对象)的数组。toLowerCase()。indexOf(searchingItem)!== -1'。 –

相关问题