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

React开发中如何将RecipeList组件的setRecipeList传递到App.js使用

React遵循单向数据流,子组件内部定义的state默认无法直接传递给父组件调用,你可以选择以下两种方案实现需求,更推荐方案一(状态提升),符合React官方设计规范。

方案一:状态提升(推荐)

把食谱列表的状态从子组件RecipeList提升到父组件App中统一管理,父组件拿到接口返回数据后直接更新状态,再将状态作为props传递给RecipeList渲染即可。

修改后的App.js代码:

import React, { useState } from "react";
import Axios from "axios";
import Header from "./Components/Header";
import RecipeList from "./Components/RecipeList";

// 注意替换为你自己的APP_ID和APP_KEY
const APP_ID = "你的应用ID";
const APP_KEY = "你的应用密钥";

function App() {
  const [timeoutId, setTimeoutId] = useState();
  // 把食谱列表状态提升到App组件
  const [recipeList, setRecipeList] = useState([]);

  const fetchRecipe = async (searchString) => {
    const response = await Axios.get(
      `https://api.edamam.com/search?q=${searchString}&app_id=${APP_ID}&app_key=${APP_KEY}`
    );
    // 接口返回后直接更新状态
    setRecipeList(response.data.hits);
  };
  const onTextChangeHandler = (e) => {
    //防抖逻辑
    clearTimeout(timeoutId);
    const timeout = setTimeout(() => fetchRecipe(e.target.value), 500);
    setTimeoutId(timeout);
  };
  return (
    <>
      <Header onTextChange = {onTextChangeHandler} />
      {/* 将食谱列表作为props传递给子组件 */}
      <RecipeList list={recipeList}/>
    </>
  );
}

export default App;

修改后的RecipeList.js代码:

import React from "react";
import Recipe from "./Recipe";
import styles from "./RecipeList.module.css";
// 直接接收父组件传递的列表数据
const RecipeList = (props) => {
  return (
    <div className={styles.recipe_list}>
      {props.list?.length > 0 &&
        props.list.map((recipeObj, index) => (<Recipe key={index} recipeObj={recipeObj.recipe} />))}
    </div>
  );
};

export default RecipeList;

注意:edamam接口返回的每条食谱数据存放在hits数组元素的recipe字段下,渲染时需要对应取值,同时给map遍历的子元素加key属性避免React报错。

方案二:通过ref暴露子组件方法(仅适合不需要频繁共享状态的场景)

如果你不想调整状态位置,可以通过forwardRef+useImperativeHandle把setRecipeList方法暴露给父组件调用:

修改后的RecipeList.js代码:

import React, { useState, useImperativeHandle, forwardRef } from "react";
import Recipe from "./Recipe";
import styles from "./RecipeList.module.css";
// 用forwardRef包裹组件接收ref参数
const RecipeList = forwardRef((props, ref) => {
  const [recipeList, setRecipeList] = useState([]);
  // 暴露方法给父组件的ref调用
  useImperativeHandle(ref, () => ({
    updateList: (newList) => setRecipeList(newList)
  }))
  return (
    <div className={styles.recipe_list}>
      {recipeList.length > 0 &&
        recipeList.map((recipeObj, index) => (<Recipe key={index} recipeObj={recipeObj.recipe} />))}
    </div>
  );
});

export default RecipeList;

修改后的App.js代码:

import React, { useState, useRef } from "react";
import Axios from "axios";
import Header from "./Components/Header";
import RecipeList from "./Components/RecipeList";

const APP_ID = "你的应用ID";
const APP_KEY = "你的应用密钥";

function App() {
  const [timeoutId, setTimeoutId] = useState();
  // 创建ref绑定到RecipeList组件
  const recipeListRef = useRef();

  const fetchRecipe = async (searchString) => {
    const response = await Axios.get(
      `https://api.edamam.com/search?q=${searchString}&app_id=${APP_ID}&app_key=${APP_KEY}`
    );
    // 调用子组件暴露的方法更新列表
    recipeListRef.current?.updateList(response.data.hits);
  };
  const onTextChangeHandler = (e) => {
    clearTimeout(timeoutId);
    const timeout = setTimeout(() => fetchRecipe(e.target.value), 500);
    setTimeoutId(timeout);
  };
  return (
    <>
      <Header onTextChange = {onTextChangeHandler} />
      {/* 绑定ref */}
      <RecipeList ref={recipeListRef}/>
    </>
  );
}

export default App;

内容的提问来源于stack exchange,提问作者M. R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 06:15:02