[Next.js][App router]使用Server Action操作MongoDB基礎方式
這篇簡要的彙整成6個步驟,演示如何以以Server Action在Next.js中操作MongoDB,輸入新的資料。
演示成果可點擊這裡進入[輸入時顯示候選清單]
1. 新增可存取MongoDB的的使用者並賦予權限
這裡要看你的MongoDB設定,以Altas來說就是在Database Access選單中增加新的使用者。
選擇並賦予讀寫你的database的權限,舉例像是下圖中呈現的Database Access權限,就是讓msadmin使用者可以讀寫member-system這個database
2. 設定Next.js環境變數,加入MONGODB_URI
MONGODB_URI變數內容會類似
MONGODB_URI="mongodb+srv://{帳號}:{密碼}@{cluster-name}.{instance-id}.mongodb.net/{Database名稱}?retryWrites=true&w=majority&appName=Cluster0"
記得.env.development.local和.env.production.local都要加入
3. 安裝mongodb套件
npm install mongodb
4. 寫mongodb存取lib
src/app/libs/mongodb.ts
import { MongoClient } from 'mongodb';
if (!process.env.MONGODB_URI) {
throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
}
const uri = process.env.MONGODB_URI;
const options = {};
export const Client = new MongoClient(uri, options);
export const Database = Client.db('<Database名稱>');
export const Collection = Database.collection('<DB底下Collection名稱>');
這裡如果是開發用,請參考mongodb官方建議的寫法,避免一直Hot reload造成大量的client連線問題。
5. 寫CRUD程式碼
這裡以AddItem的Server Action來舉例
'use server';
import { redirect, RedirectType } from 'next/navigation';
import { Collection } from '@/libs/mongodb';
export async function AddItem(formData: FormData) {
const rawFormData = {
item: formData.get('item'),
price: formData.get('price'),
quantity: formData.get('quantity'),
date: new Date(),
}
await Collection.insertOne(rawFormData);
redirect('/list', RedirectType.replace);
}
src/app/add/page.tsx
Server action搭配使用MUI v5的表單
<form action={AddItem}>
<Box gap={3}>
<TextField fullWidth label='名稱' type='text' name='item' required></TextField>
<FormControl sx={{ my: 2 }}>
<InputLabel htmlFor="adornment-price">價格</InputLabel>
<OutlinedInput
id="adornment-price"
startAdornment={<InputAdornment position='start'>$</InputAdornment>}
label="價格"
name="price"
/>
</FormControl>
<FormControl sx={{ my: 2 }}>
<InputLabel htmlFor="adornment-amount">數量</InputLabel>
<OutlinedInput
id="adornment-amount"
label="數量"
name="quantity"
/>
</FormControl>
</Box>
<Stack direction='row' spacing='auto'>
<Button
type='submit'
variant='contained'
startIcon={<AddIcon />}
>新增</Button>
<Button
variant='outlined'
href='/list'
>取消</Button>
</Stack>
</form>
留言