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

React+Axios添加菜谱失败求助:代码排查及用法指导

排查React + Axios添加菜谱失败的问题

你遇到的核心问题是Axios POST请求没有正确发送数据,同时代码里还有几处逻辑冲突和遗漏的细节,导致菜谱既没提交到后端,前端状态更新也存在隐患。下面一步步给你梳理修复方案:


1. Axios.post 未传递请求体,也未处理响应/错误

你当前的axios.post只传了接口URL,完全没把新建的菜谱数据发给后端,而且没有捕获请求错误,所以看不到任何失败提示。

修复代码:

const onSubmit = e => {
  e.preventDefault(); // 先阻止表单默认提交(避免页面刷新),顺序很重要
  
  // 注意:补上之前遗漏的ingredience字段,同时统一数据类型
  const newRecipe = {
    name: nazev,
    info: uvodni,
    ingredients: ingredience, // 要和后端接口要求的字段名对应
    description: postup,
    duration: Number(time) || 0, // 转数字,空值设为0
    score: Number(score) || 0
    // 后端会自动生成id,不需要自己随机生成
  };

  // 发送POST请求,传递请求体,同时处理响应和错误
  axios.post("https://cookbook.ack.ee/api/v1/recipes", newRecipe)
    .then(res => {
      console.log("菜谱添加成功:", res.data);
      // 用后端返回的真实数据更新前端状态(后端会返回带合法id的完整数据)
      setRecipes([...recipes, res.data]);
      // 可以在这里清空表单输入
      setNazev('');
      setUvodni('');
      setIngredience('');
      setPostup('');
      setTime(0);
      setScore(0);
    })
    .catch(err => {
      // 打印错误信息,方便排查
      console.error("添加失败:", err.response?.data || err.message);
      // 这里可以给用户显示友好的错误提示,比如弹窗或文字提示
    });
};

2. 表单内的第二个按钮会触发默认提交

你的表单里有个<button>+ Přidat</button>,默认type是submit,点击它会触发表单提交,干扰你的添加逻辑。

修复:

<button type="button">+ Přidat</button>

3. Context里的状态管理逻辑混乱(useState + useReducer混用)

你在RecipeContext.js里同时用了useState和useReducer,还定义了addRecipe却没用到,甚至传了不存在的addTransaction到Provider,这会导致状态更新冲突。

统一用useReducer管理状态:

修改RecipeContext.js:

import React, { useEffect, createContext, useReducer } from 'react';
import axios from 'axios';
import AppReducer from './AppReducer'

export const RecipeContext = createContext();

export default function RecipeProvider(props) {
  // 初始化state结构
  const initialState = {
    recipes: []
  };
  const [state, dispatch] = useReducer(AppReducer, initialState);

  // 定义添加菜谱的动作
  function addRecipe(recipe) {
    dispatch({
      type: 'ADD_RECIPE',
      payload: recipe
    });
  }

  useEffect(() => {
    axios.get('https://cookbook.ack.ee/api/v1/recipes?limit=10&offset=0')
      .then(res => {
        // 用dispatch更新初始菜谱列表
        dispatch({
          type: 'SET_RECIPES',
          payload: res.data
        });
      })
      .catch(err => console.error('获取菜谱失败:', err));
  }, []); // 空依赖数组,只在组件挂载时请求一次,避免无限循环

  return (
    <RecipeContext.Provider value={{ ...state, addRecipe }}>
      {props.children}
    </RecipeContext.Provider>
  );
}

修改AppReducer.js,添加SET_RECIPES的case:

export default (state, action) => {
  switch(action.type) {
    case 'SET_RECIPES':
      return {
        ...state,
        recipes: action.payload
      };
    case 'ADD_RECIPE':
      return {
        ...state,
        recipes: [action.payload, ...state.recipes]
      };
    default:
      return state;
  }
};

之后在Form组件里用Context的addRecipe更新状态:

// Form.js的onSubmit成功回调里替换setRecipes:
.then(res => {
  console.log("菜谱添加成功:", res.data);
  addRecipe(res.data); // 用Context统一管理的方法更新状态
})

4. 表单输入的类型处理优化

time和score是数字类型,但输入框默认返回字符串,建议转成数字同时优化输入类型:

// time输入框
<input 
  type="number" // 改成number类型,限制输入为数字
  placeholder="Čas" 
  className="cas" 
  value={time} 
  onChange={(e) => setTime(Number(e.target.value) || 0)} 
/>

// score输入框
<input 
  type="number"
  min="0" max="5" // 如果评分是0-5,可以加范围限制
  value={score} 
  onChange={(e) => setScore(Number(e.target.value) || 0)} 
/>

测试排查技巧

  1. 打开浏览器开发者工具(F12),切换到Network标签,点击添加按钮后查看POST请求的详情:
    • 看Request Body是否包含你输入的菜谱数据
    • 看Response Status:201表示创建成功,4xx是客户端参数错误,5xx是服务端问题
  2. 查看Console标签,看有没有错误信息,快速定位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:04:53