在 React 中渲染具有不同状态的组件数组

Posted

技术标签:

【中文标题】在 React 中渲染具有不同状态的组件数组【英文标题】:Rendering an array of components with seperate states in React 【发布时间】:2021-06-02 22:21:15 【问题描述】:

好的!因此,已经提出了与此类似的问题,但问题是它们不能解决我的确切问题,因此请阅读完整的问题并考虑查看下面粘贴的代码 sn-p,然后再将其标记为重复。所以我有一个对象数组menuItems,其中包含另一个组件MenuItem 的道具,我试图通过迭代该数组“menuItems”并分配独特的道具来多次渲染该组件MenuItem然后将其推送到另一个名为 items 的数组,完成后我将这个 items 数组放在返回中,但不知何故反应根本不会呈现该数组。

function Menu() 

    let items = [];

    const menuItems = [
        
            imageName:'food-header-2.jpg',
            itemTitle:'Full breakfast for morning',
            itemPunchLine:'Some punchline',
            quantity:0,
        ,
        
            imageName:'pizza.jpg',
            itemTitle:'Cheeze pizza',
            itemPunchLine:'Some punchline',
            quantity:0,
        ,
        
            imageName:'burger.jpg',
            itemTitle:'Jumbo Burger',
            itemPunchLine:"Some punchline",
            quantity:0,
        ,
        
            imageName:'sandwich.jpg',
            itemTitle:'Veg SandWich',
            itemPunchLine:'Some punchline',
            quantity:0,
        ,
        
            imageName:'chocolate-shake.jpg',
            itemTitle:'Chocolate Shake',
            itemPunchLine:'Some punchline',
            quantity:0,
        ,
    ]

    const useEffect(() => 

        menuItems.forEach((menuItem,index) => 
            items.push(
            <MenuItem key=index title=menuItem.itemTitle punchLine=menuItem.itemPunchLine 
            quantity=menuItem.quantity imageName=menuItem.imageName
            />);
        ));

        
    ;
    return(
        <div className="container">
            <div className="menu-holder">
                <div className="menu">
                    items                 
                </div>
            </div>            
        </div>
    )

【问题讨论】:

【参考方案1】:

items 是一个普通数组。它不是一个有状态的值(即使用 useState 钩子)。当这个值改变时,React 不会重新渲染。

您应该在返回语句中直接使用map 呈现menuItems

 return(
    <div className="container">
        <div className="menu-holder">
            <div className="menu">
                menuItems.map((menuItem,index) => 
                  <MenuItem
                    key=index 
                    title=menuItem.itemTitle 
                    punchLine=menuItem.itemPunchLine 
                    quantity=menuItem.quantity
                    imageName=menuItem.imageName
                  />)
            </div>
        </div>
    </div>
)

...

如果您出于某种原因想要保留 items 数组,要遵循这种方法,您需要将其转换为反应状态。

你可以这样实现它:

import React,  useEffect, useState  from "react";

const menuItems = [
  
      imageName:'food-header-2.jpg',
      itemTitle:'Full breakfast for morning',
      itemPunchLine:'Some punchline',
      quantity:0,
  
]

function Menu() 
  const [items, setItems] = useState([]);

  useEffect(() => 
    setItems(menuItems)
  , [])

  return(
      <div className="container">
          <div className="menu-holder">
              <div className="menu">
                items.map((menuItem,index) => 
                  <MenuItem
                    key=index 
                    title=menuItem.itemTitle 
                    punchLine=menuItem.itemPunchLine 
                    quantity=menuItem.quantity
                    imageName=menuItem.imageName
                  />)
              </div>
          </div>
      </div>
  )

但是,如果您在渲染时知道 menuItems,那么直接将初始状态设置为此会更有效(而不是在渲染后在 useEffect 挂钩中设置它:

  const [items, setItems] = useState(menuItems);

【讨论】:

这工作得非常好,但后来我尝试在useEffect 钩子中使用相同的array.map,然后尝试渲染它停止工作的数组并做出反应会引发错误Objects are not valid as React Child 我想问为什么会这样? map 如何使数组有状态? 我已经扩展了答案,以尝试显示您应该使用的模式。 map 在 React 中没有使值有状态,它只是一种迭代数组并返回新数组的方法。【参考方案2】:

为了让 React 观察状态变化,您可以使用 useState 挂钩来跟踪数组状态的变化。

const [items, setItems] = useState([])

【讨论】:

你的意思是我应该在menuItems.forEach 循环内执行setItems([...items, newItem]) 吗?

以上是关于在 React 中渲染具有不同状态的组件数组的主要内容,如果未能解决你的问题,请参考以下文章

React 功能组件中状态更改后组件未重新渲染

05react 之 组件state

javascript REACT:在无状态功能组件中渲染对象数组

React 中基于当前组件状态的条件渲染

更改数组中的一个状态会导致在 React Hooks 中重新渲染整个循环生成的自定义组件

为 React Native SectionList 的每个部分渲染不同的组件