做的一个简单需求管理系统,将 Action 方法提取到单独的文件中,这样代码更具模块化,易于维护。将 Action 方法移到单独的 actions.ts 文件中,然后在需要的地方引入并调用它。
1. 创建 actions.ts 文件
actions.ts
import prisma from '@/lib/prisma';
export async function createRequirement(code: string, name: string, description: string) {
try {
const newRequirement = await prisma.requirement.create({
data: {
code,
name,
description,
},
});
return newRequirement;
} catch (error) {
console.error('Error creating requirement:', error);
throw new Error('Failed to create requirement');
}
}
2. 更新 page.tsx 文件
接下来,在 page.tsx 文件中,移除 createRequirement 方法的定义,并从 actions.ts 文件中导入它。
page.tsx
'use server'
import { useState } from 'react';
import { RequirementModal } from './modal';
import { createRequirement } from './actions';
export default function RequirementsPage() {
const [requirements, setRequirements] = useState<any[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const fetchRequirements = async () => {
const res = await fetch('/api/requirements');
const data = await res.json();
setRequirements(data);
};
const handleCreateRequirement = async (code: string, name: string, description: string) => {
try {
const newRequirement = await createRequirement(code, name, description);
setRequirements((prev) => [...prev, newRequirement]);
setIsModalOpen(false);
} catch (error) {
console.error('Failed to create requirement:', error);
}
};
useState(() => {
fetchRequirements();
}, []);
return (
<div>
<h1>需求列表</h1>
<div>
<button onClick={() => setIsModalOpen(true)}>新增需求</button>
</div>
<div>
{requirements.length > 0 ? (
<ul>
{requirements.map((requirement) => (
<li key={requirement.id}>
{requirement.code} - {requirement.name}
</li>
))}
</ul>
) : (
<p>暂无需求</p>
)}
</div>
{}
{isModalOpen && <RequirementModal onCreate={handleCreateRequirement} />}
</div>
);
}
3. 更新 modal.tsx 文件
保持 modal.tsx 文件不变,只需确保它与父组件进行正确的通信。
modal.tsx
import { useState } from 'react';
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogClose } from '@shadcn/ui/dialog';
export function RequirementModal({ onCreate }: { onCreate: (code: string, name: string, description: string) => void }) {
const [code, setCode] = useState('');
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const handleCreate = () => {
onCreate(code, name, description);
};
return (
<Dialog>
<DialogTrigger asChild>
<button className="btn">新增需求</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>创建新需求</DialogHeader>
<div>
<label htmlFor="code">需求代码</label>
<input id="code" type="text" value={code} onChange={(e) => setCode(e.target.value)} required />
</div>
<div>
<label htmlFor="name">需求名称</label>
<input id="name" type="text" value={name} onChange={(e) => setName(e.target.value)} required />
</div>
<div>
<label htmlFor="description">需求描述</label>
<textarea id="description" value={description} onChange={(e) => setDescription(e.target.value)} required />
</div>
<DialogFooter>
<DialogClose asChild>
<button onClick={handleCreate}>创建需求</button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}