iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
Modern Web

MERN Stack + Tailwind CSS - React 小專案實踐計畫系列 第 19

【Day 19】取得單一文章資料 - Model.findById()

  • 分享至 

  • xImage
  •  

之前使用了 Mongoose 的 Model.find() 來取得所有文章的資料,這次使用也十分常見的 Model.findById() 來取得單一文章的詳細資料內容~

利用文件 id 找資料 → Model.findById()

一樣在 server/index.js 中新增 GET api :

  • 在 url 路徑中加上 /:id 來接收參數(params)
  • 使用 .findById() 並傳入 req.params.id (也就是 url 中的 /:id
app.get('/api/v1/posts/:id', async (req, res) => {
    try {
        const post = await Post.findById(req.params.id);
        res.status(200).json({
            status: 'success',
            data: {
                data: post,
            },
        });
    } catch (err) {
        console.log(err);
        res.json({
            status: 'error',
        });
    }
});

接著回到前端的 client/src/api/index.js

與之前的 getAllPost 相同,只多了一個 id 需要傳入~

export const getPost = async ({ id }) => {
    try {
        const res = await axios.get(`${baseUrl}api/v1/posts/${id}`);
        return res.data;
    } catch (err) {
        console.log(err.response);
        alert('讀取文章失敗 (|||゚д゚)');
    }
};

最後我們就能來到 client/src/pages/PostDetail.js 來修改程式碼啦

  • 同樣引入 useState, useEffect 以及 api getPost
  • 宣告狀態變數 post 並設定初始值為空物件 {}
  • 使用 useEffect 在頁面渲染時呼叫 getPost api,並將從 url 取得的參數 id 傳進去
import React, { useState, useEffect } from 'react';
import { getPost } from '../api';

const [post, setPost] = useState({});

useEffect(() => {
    fetchPost();
}, []);

const fetchPost = async () => {
    const res = await getPost({ id });
    setPost(res.data.data);
};

目前程式碼

https://ithelp.ithome.com.tw/upload/images/20221003/20152502M31uyn0ABE.png

成功在 PostDetail.js 正常顯示資料~

https://ithelp.ithome.com.tw/upload/images/20221003/20152502UYtcpynOrO.png

處理日期顯示

目前文章的建立日期是用 Date.now() 產生的時間格式,但對於前端來說,我們可能只需要顯示日期或是幾時幾分,並不需要到毫秒這樣準確,所以現在來另外處理這部分!

  • PostDetail.js 中建立 formatDate() 函數
  • 接收 date 參數,並宣告變數 d 利用 new Date() 解析 date 日期物件
  • 同時宣告多個變數 → 用逗號 , 隔開
  • 利用 Date 物件的 method 來取得 年、月、日
  • 加上空字串 ‘’ 讓回傳的月和日的型別從數字變成字串
  • getMonth() 回傳的月份從 0 開始,所以要加額外 +1(例如:一月 → 0, 二月 → 1)
  • 判斷月和日是否小於二位數,若小於則在前方加上字串 ‘0’
  • 最後回傳處理好的日期,將年月日放進陣列中,並用 .join('/') 以「/」合併為單一字串
const formatDate = (date) => {
    let d = new Date(date),
        year = d.getFullYear(),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate();

    if (month.length < 2) month = '0' + month;
    if (day.length < 2) day = '0' + day;

    return [year, month, day].join('/');
};

因為專案中許多元件都會需要用到 formatDate() 函數,所以我們可以把它額外取出來:

  • 建立 client/src/utils 資料夾,並新增 formatter.js 檔案
  • 然後把剛剛的程式碼複製過來,並輸出 export
  • 在需要用到的元件中引入即可!

https://ithelp.ithome.com.tw/upload/images/20221003/201525029vP9VBuU2L.png

https://ithelp.ithome.com.tw/upload/images/20221003/20152502ShQENlvcpR.png


上一篇
【Day 18】從資料庫獲取資料 - Model.find()
下一篇
【Day 20】免費的雲端資料庫 - MongoDB Atlas
系列文
MERN Stack + Tailwind CSS - React 小專案實踐計畫30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言