【AI coding】React对接后端接口实现入门级小工具todolist

前言

最近在使用Trae辅助开发。有一说一,至少目前来说AI编程和理想状态还是有点差距的。主要体现在以下几大方面:

  • 需要给出非常明确、细化的需求,否则如果连用户自己都没有想清楚要做什么或者只是给了个大致方向的话,AI给出来的代码只会越来越混乱,前后衔接不上。因为本质上AI目前并不是真的在思考,相应的上下文处理能力是有限的,只是在生成一段符合语义规则的文本而已。
  • 针对通用的产品方案效果好,但是不适合需要高度定制化的场景。归根结底应该是数据库还不够完善和全面。
  • 编码人员还是应该要具备一定的技术能力,至少要能看懂代码并修正。当前AI生成的代码或多或少还是存在一些错误,如果看不懂,只是告诉它"错了,请修改",很有可能就开始绕圈圈但不解决实际问题,或者改了a错误又出现了b错误。正确的做法应该是把它作为辅助,选择性摘取适合自己的部分,最大程度保证不引入新bug;不要养成过度依赖AI的习惯,遇到错误先自己静下心排查,把具体原因告诉它,让它出解决方案;或者自己先尝试排查一遍,不行再找它帮忙。是工具为人服务,而不是人为工具服务。类比现实中的场景就是:老板可以听取下属的建议,但是决策权还是在自己手上。一定要自己做好调研,而不能完全只听下属汇报的一面之词。

以下是我通过Trae完成todolist小工具的完整过程:

后端实现

后端用的是c#,相应的代码是现成的,可在微软官网找到: # 教程:使用 ASP.NET Core 创建最小 API

微修了一下Program.cs文件中对于接口的定义:

c# 复制代码
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// 配置静态文件服务(自动使用 wwwroot 目录)
app.UseStaticFiles();
app.UseDefaultFiles(); // 自动提供 index.html

// 内存存储
var todos = new List<TodoItem>();
var nextId = 1;

// API 路由组
var todoApi = app.MapGroup("/api/todoitems");

todoApi.MapGet("/", () => todos);
todoApi.MapGet("/complete", () => todos.Where(t => t.IsComplete));
todoApi.MapGet("/{id}", (int id) => 
    todos.FirstOrDefault(t => t.Id == id) is TodoItem todo 
        ? Results.Ok(todo) 
        : Results.NotFound());

todoApi.MapPost("/", (TodoItem item) => {
    var newItem = new TodoItem(nextId++, item.Title, item.IsComplete);
    todos.Add(newItem);
    return Results.Created($"/api/todoitems/{newItem.Id}", newItem);
});

todoApi.MapPut("/{id}", (int id, TodoItem updatedItem) => {
    var index = todos.FindIndex(t => t.Id == id);
    if (index == -1) return Results.NotFound();
    
    todos[index] = updatedItem with { Id = id };
    return Results.NoContent();
});

todoApi.MapDelete("/{id}", (int id) => {
    var count = todos.RemoveAll(t => t.Id == id);
    return count > 0 ? Results.NoContent() : Results.NotFound();
});

// 处理 SPA 路由:所有未匹配的请求返回 index.html
app.MapFallbackToFile("/index.html");

app.Run();

// 使用记录类型定义模型
public record TodoItem(int Id, string Title, bool IsComplete);

前端代码

本项目出于方便考虑,不进行前后端分离。只是在原后端项目的基础上加入页面代码。具体操作如下: 在项目根目录下新建wwwroot文件夹,在其中分别新建index.html、style.css、app.js三个文件。

index.html

index.html的作用是引入react,关键代码:

html 复制代码
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

style.css

作用是定义界面的各种样式。值得一提的是标记为已完成的功能:

css 复制代码
.todo-list li.completed .todo-title {
  text-decoration: line-through;
  color: #888;
}

通过上述代码给状态标记为已完成的事项添加删除线,字体变暗。 为了能应用这种效果,app.js的return代码中要给对应的li标签加上类名。

app.js

最初AI生成的代码中,勾选了完成的复选框后,对应事项内容就消失了。原因是在调用修改事项的接口时,只传入状态,没有传入文本内容字段(相当于把内容修改为空串了),代码修改后如下:

js 复制代码
  // 更新待办事项内容(含状态和文本)
  const saveEdit = async (id, currentStatus) => {
    if (!editText.trim()) {
      showNotification("事项内容不能为空", true);
      return;
    }

    try {
      const response = await fetch(`/api/todoitems/${id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: editText, isComplete: currentStatus }),
      });

      if (!response.ok) throw new Error("更新失败");

      showNotification("事项更新成功");
      setEditText("");
      setEditingId(null);
      fetchTodos();
    } catch (error) {
      console.error("更新失败:", error);
      showNotification("更新失败", true);
    }
  };

此外,还增加了双击对应文本框可编辑事项、按回车完成更新的功能: 在return代码中加入:

js 复制代码
              {editingId === todo.id ? (
                // 编辑模式:显示输入框
                <input
                  type="text"
                  value={editText}
                  onChange={(e) => setEditText(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") saveEdit(todo.id, todo.isComplete); // 回车保存
                    if (e.key === "Escape") setEditingId(null); // 按ESC取消
                  }}
                  autoFocus // 自动聚焦输入框
                />
              ) : (
                // 只读模式:双击进入编辑
                <span
                  className="todo-title"
                  onDoubleClick={() => {
                    setEditingId(todo.id);
                    setEditText(todo.title); // 初始化编辑内容为原标题
                  }}
                >
                  {todo.title}
                </span>
              )}

最终效果

本来想放图片的,但是上传了几次都没成功。其实也只是经典款,白底背景,蓝红按钮,没什么好看的。我在几个视频平台也上传了演示视频。

相关推荐
豆包MarsCode7 小时前
5 个技巧教你用 SOLO 做复杂数据分析
trae
Hector_zh13 小时前
逐浪 · 第八篇:移动端实战:用 TRAE SOLO 完成 Git 问题深度分析与博客优化
人工智能·trae
大手你不懂13 小时前
Trae 调用 MiMo API 报错 400?一文搞懂原因并用 Proxy 完美解决
trae
一点一木1 天前
深度体验TRAE SOLO移动端7天:作为独立开发者,我把工作流揣进了兜里
前端·人工智能·trae
小郭的笔记2 天前
在 Trae SOLO 模型下,我是怎么用 JS + Python 啃下像素画解析算法的
trae
小怼子2 天前
TRAE 官方没有做的桌宠,我用 TRAE SOLO 给做出来了
trae
小雄Ya3 天前
构建AI导师,通勤路上偷偷学习惊艳所有人
agent·trae
飞哥数智坊3 天前
TRAE SOLO 三端接力,救了我一场分享会
人工智能·trae
鹏多多3 天前
Trae cn里使用Pencil来制作设计图的手把手教程
前端·ai编程·trae
FEF前端团队3 天前
AI 编程 Agent 全景解读:从 Chat 到 Agent,你的代码助手进化到了哪一步?
ai编程·cursor·trae