Remix Run向服务端发送数据及useActionData使用问题求助
Remix 提交POST请求问题解答
核心疑问明确
- 路由模块导出的
action函数就是编写POST等变更类请求逻辑的正确位置。它和处理GET请求的loader同属服务端执行逻辑,不会被打包到客户端代码中。 - 你遇到
createCart is not a function报错的根本原因:createCart是服务端执行的方法,你直接在客户端点击事件回调里调用,客户端作用域根本访问不到服务端定义的函数,自然会抛出不存在的错误。
点击按钮提交数据的正确实现
- 先把创建购物车的核心逻辑迁移到
action函数中,从请求中解析参数、完成服务端调用后返回结果即可,参考代码:
// 该函数仅在服务端运行,不会暴露给浏览器 export async function action({ request }) { // 解析客户端提交的参数 const formData = await request.formData(); const goodsId = formData.get("id"); const num = formData.get("amount"); // 这里直接执行你的createCart逻辑,调用内部接口/操作数据库都可以 const cartInfo = await createCart(goodsId, Number(num)); // 返回执行结果,客户端可通过useActionData直接获取 return { code: 0, data: cartInfo, msg: "创建成功" }; }
- 客户端触发提交可根据场景二选一:
- 优先用Remix提供的
Form组件,无需手写点击事件,点击提交按钮会自动向当前路由action发POST请求,代码最简洁:
import { Form, useActionData } from "@remix-run/react"; export default function GoodsPage() { // 获取action返回的结果,行为和useLoaderData一致,action执行后会自动同步更新 const actionRes = useActionData<typeof action>(); return ( <div> <Form method="post"> {/* 隐藏域传参,也可以是可见的表单项 */} <input type="hidden" name="id" value="当前商品id" /> <input type="hidden" name="amount" value={1} /> <button type="submit">加入购物车</button> </Form> {actionRes?.code === 0 && <span>加入购物车成功</span>} </div> ) }- 如果需要先执行客户端校验、交互逻辑再提交,就用你已经引入的
useSubmit钩子手动触发提交,不要直接调用服务端方法:
import { useSubmit, useActionData } from "@remix-run/react"; export default function GoodsPage() { const submit = useSubmit(); const actionRes = useActionData<typeof action>(); const handleClick = () => { // 这里可以写提交前的客户端逻辑,比如参数校验、埋点上报 const submitData = { id: "当前商品id", amount: 1 }; // 调用submit提交数据,自动触发对应action执行 submit(submitData, { method: "post" }); }; return ( <div> <button onClick={handleClick}>加入购物车</button> {actionRes?.code === 0 && <span>加入购物车成功</span>} </div> ) } - 优先用Remix提供的
注意:不要把带密钥的接口调用、数据库操作这类逻辑写到客户端组件代码里,Remix会自动对loader/action和客户端代码做隔离打包,避免敏感信息泄露。
内容的提问来源于stack exchange,提问作者marcuspetty
相关产品推荐
相关产品推荐

