[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>


6. 完工!


留言