【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>
              )}

最终效果

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

相关推荐
bytebeats14 分钟前
Trae 2.0 Solo: 这并非又一个 Copilot
trae
bytebeats36 分钟前
使用 Trae 进行 iOS 开发
trae
程序员爱钓鱼2 小时前
Go语言实战案例:使用channel实现生产者消费者模型
后端·go·trae
程序员爱钓鱼2 小时前
Go语言实战案例:使用select监听多个channel
后端·go·trae
飞哥数智坊13 小时前
AI编程实战:使用Trae从零开始实现写作助手的后端开发及前后端联调
人工智能·trae
豆包MarsCode16 小时前
插件升级:Chat/Builder 合并,支持自定义 Agent、MCP、Rules
trae
你不会困18 小时前
看看Trae怎么实现五彩斑斓的黑
trae
用户40993225021219 小时前
FastAPI后台任务为何能让邮件发送如此丝滑?
后端·github·trae
逸风尊者1 天前
开发也能看懂的大模型:聚类
人工智能·后端·trae