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

如何让useQuery查询到的食谱数据正确赋值到useState定义的表单状态中?

问题原因
  • useQuery 是异步请求逻辑,组件首次渲染时请求还未返回,data 为 undefined,此时你用 data?.recipe || {} 得到的是空对象,赋值给 useState 作为初始值自然所有属性都是 undefined。而 useState 的初始值仅会在组件第一次渲染时执行一次,后续请求成功拿到 data 后,状态也不会自动更新。
  • 代码中存在属性拼写错误:recipe.cateogry 应为 recipe.category,拼写错误会导致即使数据返回也取不到对应值。
  • 你提前处理的 ingredientList、directionList 字符串变量并未在初始化 useState 时使用,如果你表单中食材、步骤对应是多行文本框,需要把数组转成带换行的字符串赋值,否则直接用数组渲染到文本框会默认调用toString(),逗号分隔不符合预期。
修复方案

用 useEffect 监听 data 和 loading 的变化,当请求完成、数据返回后再手动更新 updateRecipe 状态,同时加载阶段可以做加载态展示避免报错。

import { useEffect } from 'react';

const { recipeId } = useParams();

const { loading, data } = useQuery(QUERY_SINGLE_RECIPE, {
    variables: { recipeId: recipeId },
});

// 初始化状态给默认空结构,避免读取属性时报错
const [updateRecipe, setUpdateRecipe] = useState({
    title: '',
    category: '',
    servings: '',
    totalTime: '',
    ingredients: '',
    directions: '',
    imageid: ''
});

// 监听data变化,请求成功后更新状态
useEffect(() => {
    if (!loading && data?.recipe) {
        const recipe = data.recipe;
        // 数组转多行字符串,适配表单textarea输入,如果是多输入框数组形式可省略转换直接用原数组
        const ingredientList = recipe.ingredients?.join('\r\n') || '';
        const directionList = recipe.directions?.join('\r\n') || '';
        
        setUpdateRecipe({
            title: recipe.title || '',
            category: recipe.category || '', // 修正拼写错误
            servings: recipe.servings || '',
            totalTime: recipe.totalTime || '',
            ingredients: ingredientList,
            directions: directionList,
            imageid: recipe.imageid || ''
        });
    }
}, [loading, data]); // 依赖项添加loading和data,变化时触发执行
补充说明

如果你的表单食材、步骤是多输入框数组形式,不需要做数组转字符串的处理,直接把原始数组赋值给对应字段即可;渲染表单前可以判断loading状态,加载中时展示加载提示,避免用户看到空表单。

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

相关产品推荐
方舟 Agent Plan

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

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