You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React卡片中按需循环渲染食材的实现方法

如何在React食谱卡片中循环渲染指定数量的食材

核心思路:替换硬编码食材列表为动态循环

你的代码目前手动写了14个Card.Text展示食材,既冗余又无法灵活控制数量。可以通过以下几步实现按需展示:


1. 编写工具函数提取结构化食材数据

API返回的食材是strIngredient1到strIngredient20这类零散字段,先把它们转换成数组,同时过滤空值(很多食谱的后续食材字段为空):

const getIngredients = (meal) => {
  const ingredients = [];
  // 遍历API支持的最多20种食材
  for (let i = 1; i <= 20; i++) {
    const ingredient = meal[`strIngredient${i}`];
    const measure = meal[`strMeasure${i}`];
    // 只保留有实际内容的食材
    if (ingredient && ingredient.trim()) {
      ingredients.push({ name: ingredient, measure });
    }
  }
  return ingredients;
};

2. 给每个食谱设置自定义显示数量

你需要每张卡片展示不同数量的食材,比如卡片1显示5种、卡片2显示10种,可以在获取API数据后给每个食谱添加自定义字段:

.then((json) => {
  const processedMeals = json.meals?.map((meal, index) => ({
    ...meal,
    // 这里用索引奇偶区分,你也可以改成自己的规则(比如从后端获取、手动配置)
    displayCount: index % 2 === 0 ? 5 : 10
  })) || [];
  setData(processedMeals);
});

3. 用循环渲染指定数量的食材

把原来硬编码的Card.Text替换成循环,只渲染设定数量的食材:

<div id='ing'>
  {/* 先获取食材数组,再截取前N个(N为自定义的displayCount) */}
  {getIngredients(res).slice(0, res.displayCount).map((ing, idx) => (
    <Card.Text key={idx}>{ing.name}-{ing.measure}</Card.Text>
  ))}
</div>

完整修改后的组件代码

function LiveData() {
  const [mydata, setData] = useState([]);

  // 提取食材的工具函数
  const getIngredients = (meal) => {
    const ingredients = [];
    for (let i = 1; i <= 20; i++) {
      const ingredient = meal[`strIngredient${i}`];
      const measure = meal[`strMeasure${i}`];
      if (ingredient && ingredient.trim()) {
        ingredients.push({ name: ingredient, measure });
      }
    }
    return ingredients;
  };

  const api = () => {
    // 修正原代码fetch的错误:第二个参数传错,已移除
    fetch("https://www.themealdb.com/api/json/v1/1/search.php?s=")
      .then((response) => response.json())
      .then((json) => {
        // 给每个食谱添加自定义食材显示数量
        const processedMeals = json.meals?.map((meal, index) => ({
          ...meal,
          displayCount: index % 2 === 0 ? 5 : 10
        })) || [];
        setData(processedMeals);
      });
  };

  useEffect(() => {
    api();
    const interval = setInterval(() => {
      api();
    }, 20000);
    return () => clearInterval(interval);
  }, []);

  return (
    <>
      <Container fluid>
        <Row xs={1} md={3} className="g-4">
          {mydata.map((res, idx) => (
            {/* React列表渲染必须添加唯一key */}
            <Col key={idx} className="container-fluid mt-4">
              <Card>
                <Card.Img variant="top" src={res.strMealThumb} height="340px" width="500px" />
                <Card.Body>
                  <Card.Title>{res.strMeal}</Card.Title>
                  <Card.Text>{res.strArea}</Card.Text>
                  <b>Ingredients: </b>
                  <div id='ing'>
                    {getIngredients(res).slice(0, res.displayCount).map((ing, ingIdx) => (
                      <Card.Text key={ingIdx}>{ing.name}-{ing.measure}</Card.Text>
                    ))}
                  </div>
                  <Card.Link>
                    <a
                      href={res.strYoutube}
                      target="_blank"
                      rel="noopener noreferrer" // 符合安全规范,防止钓鱼攻击
                    >
                      YouTube Video for {res.strMeal}
                    </a>
                  </Card.Link>
                </Card.Body>
              </Card>
            </Col>
          ))}
        </Row>
      </Container>
    </>
  );
}

额外提示

  • 原代码中fetch的第二个参数是错误的,fetch的第二个参数是请求配置(如POST的body),不是查询参数,已修正
  • 给所有列表项添加了key属性,避免React渲染警告
  • 如果需要动态调整显示数量(比如添加"显示更多"按钮),可以给每个卡片单独维护状态,点击时修改displayCount的值

内容的提问来源于stack exchange,提问作者Priya Prajapati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:45:54