微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用ReactJS将Firebase数组中的每个值渲染为<li>

如何解决使用ReactJS将Firebase数组中的每个值渲染为<li>

我正在开发食谱应用程序,但在从Firebase阵列渲染我的成分列表时遇到一些问题。我是JS和React的新手,所以如果这很简单,我深表歉意。我非常感谢所提供的任何帮助!我已经附上了我的代码,并提供了当前如何呈现数组的示例。我还提供了Firebase数据结构的屏幕截图。 [firebaseStructure] [1]


useEffect(() =>{

  database.collection('recipes').onSnapshot(snapshot => {
    setRecipeCard(snapshot.docs.map(doc => ({id:doc.id,recipes:doc.data()})));
    console.log(snapshot.docs.map(doc => ({id:doc.id,recipes:doc.data()})))
  })  
  },[]);

  useEffect(() =>{
    
    database.collection('recipes').onSnapshot(snapshot =>{

      setIngredientsList(snapshot.docs.map(doc =>({id:doc.id,ingredient: doc.data().ingredients1})));
      console.log(snapshot.docs.map(doc =>({id:doc.id,ingredient: doc.data().ingredients1})))
    })
  },[]);

  return (
    <div>
      <Container>
      <Row>

      {recipeCard.map(recipes =>(
      
        <Col md={4} key={recipes.id}>
          <Card style={{ width: '100%' }}>
              <Card.Img variant="top" src={recipes.recipes.url} style={{height:'300px',width:'100%'}} />
              <Card.Body>
                <Card.Title>{recipes.recipes.title}</Card.Title>
                {/**<Card.Text> **/}
                <ul key={recipes.id}>
                  {ingredientsList.map(recipes =>(
                  <li key={recipes.id}>
                      {recipes.ingredient}
                  </li>
                  ))}
                </ul>
                {/** </Card.Text> **/}
              <Button variant="secondary">Head to Recipe</Button>
            </Card.Body>
          </Card>
          </Col>   
          
      ))}
      </Row>
      </Container>
    </div>
  )
}

[current rendered output][2]


  [1]: https://i.stack.imgur.com/bFBdr.png
  [2]: https://i.stack.imgur.com/xU1fC.png

解决方法

您不需要在两个单独的useEffect中两次调用数据库来执行所需的操作。在这种情况下,为了提高效率,您只需调用一次DB。

此外,您还要在第二个映射中声明recipes,这可能会导致错误,您应该避免对不同的变量使用相同的变量名。您的问题可能与此有关。假设您仅将第一个useEffectsetRecipeCard一起使用,我编辑了以下代码。

{recipeCard.map(recipe =>(
  <Col md={4} key={recipe.id}>
    <Card style={{ width: '100%' }}>
      <Card.Img variant="top" src={recipe.recipes.url} style={{height:'300px',width:'100%'}} />
        <Card.Body>
          <Card.Title>{recipe.recipes.title}</Card.Title>
          {/**<Card.Text> **/}
            <ul key={recipe.id}>
              {recipe.ingredients1.map(ingredient =>(
                <li key={recipes.id}>
                  {ingredient}
                </li>
               ))}
             </ul>
             {/** </Card.Text> **/}
             <Button variant="secondary">Head to Recipe</Button>
      </Card.Body>
    </Card>
  </Col>        
))}

您可以试用此代码吗?如果您遇到任何错误,请具体告诉我们:)

,

我认为,此处的许多混淆来自命名约定,以及尝试为recipieCardingredientsList使用单独的状态。您最终呈现了所有食谱的所有要素,而不仅仅是与该食谱相关的要素。如果您发现自己访问诸如recipies.recipies之类的属性,那么就知道需要进行一些重构(如果您完全控制了项目)。

首先,您只需要一个useEffect即可访问数据库并处理数据。它们都属于同一类,因此无需将其分成单独的状态。请注意,我是如何将状态重命名为recipieCards的复数形式。这是数据对象的数组或列表,因此应具有多个名称。现在,每个数据对象都具有属性data而不是recipies,该属性可以更准确地描述其包含的内容(即,一个配方的数据)。

useEffect(() =>{
  database.collection('recipes').onSnapshot(snapshot => {
      setRecipeCards(snapshot.docs.map(doc => ({id:doc.id,data:doc.data()})));
      console.log(snapshot.docs.map(doc => ({id:doc.id,data:doc.data()})))
  })  
},[]);

现在,在返回函数中,发生的事情变得更加清楚。我们采用recipieCards数组并对其进行映射,以一次访问每个收件人数据对象。对于每个数据对象,请使用id作为其键,并从data中获取url和标题。现在,您可以直接在属性data.ingredients1下从同一数据对象访问该食谱的成分。

return (
    <div>
      <Container>
        <Row>
          {recipeCards.map(recipe =>(
              <Col md={4} key={recipe.id}>
                  <Card style={{ width: '100%' }}>
                      <Card.Img variant="top" src={recipe.data.url} style={{height:'300px',width:'100%'}} />
                      <Card.Body>
                          <Card.Title>{recipe.data.title}</Card.Title>
                           {/**<Card.Text> **/}
                              <ul>
                                  {recipie.data.ingredients1.map(ingredient =>(
                                      <li key={ingredient}>
                                          {ingredient}
                                      </li>
                                  ))}
                              </ul>
                           {/** </Card.Text> **/}
                          <Button variant="secondary">Head to Recipe</Button>
                      </Card.Body>
                  </Card>
              </Col>       
          ))}
        </Row>
      </Container>
    </div>
);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。