ซีรีย์เรียนเร็วเป็นเร็ว Rapid Series วันนี้เราจะหยิบ NextJS และ Firebase Cloud Fire Store มาใช้งานกันสำหรับการแสดงผลข้อมูลบน Web Application
ก่อนอื่นสิ่งที่เราต้องทำความเข้าใจก่อนนั่นคือ เราจำเป็นต้องใช้ NodeJS ในการติดตั้ง Package ของ NextJS ซึ่งเจ้า Next.js เป็นตระกูล React Web Framework ที่ทำงานได้สะดวกช่วยให้เราเขียนเว็บได้สะดวกขึ้น แต่แน่นอนว่ามันมีราคาต้องจ่ายก่อนเรียนบทเรียนนี้นั่นคือ คุณจะต้องมีพื้นฐาน HTML & CSS และต้องเข้าใจหลักของ JavaScript เบื้องต้น และจะดีมากถ้าหากมีความเข้าใจพื้นฐาน React.js มา
ก่อนอื่นติดตั้ง NodeJS และ Visual Studio Code ให้เรียบร้อย เปิด Node Command Line หรือ Terminal ขึ้นมา (เปิดผ่าน Visual Studio Code, VS Code ก็ดี)
ไปที่ Folder ที่เราติดตั้งไว้หลังจากนั้นพิมพ์คำสั่ง:
npm init next-app
ก็จะเห็นว่า NextJS นั้นเราไม่ต้อง Config อะไรเพิ่มเลยในส่วนของ Node ต่อมาให้ไปที่ Folder ของเราในตัวอย่างตั้งว่า “project”
cd project
ทำการทดสอบเว็บแรกของเราด้วย
npm run serve
ระบบจะ Serve จำลองให้เราเข้าที่ http://localhost:3000 และเราจะเห็นหน้าแรกของเว็บไซต์เราแบบนี้:
เชยชมให้พอใจเราจะลบทิ้งแล้วไปใช้งาน CSS Bootstrap framework กันให้รันคำสั่งต่อไปนี้ใน CMD, Terminal
npm install newsapi react-bootstrap bootstrap
ระบบจะทำการติดตั้งและสร้าง ชุดคำสั่ง Template ให้เรียบร้อย ขั้นตอนต่อมาเราไปดู Folder ของ Project เราจะเห็นโครงสร้างดังนี้:
pages/ public/
ให้เราสร้าง Folder เพิ่มเข้าไปใน “components” และ “config” ใน Level เดียวกัน
components/ config/ pages/ public/
เข้าไปที่ pages/index.js แก้ไขไฟล์ ลบ Code เดิมออกแล้วพิมพ์ Code ต่อไปนี้:
const Index = () => ( <> <main style={{display: 'flex', flexDirection: 'column', alignItems:'center'}}> <h1>Content Management System</h1> </main> </> ) export default Index
หลังจากนั้นให้ไปสร้างไฟล์ชื่อ Header.js ที่โฟลเดอร์ “pages”
import Head from 'next/head'; import {Navbar, Nav, NavDropdown} from 'react-bootstrap'; const Header = () => ( <div style={{ marginBottom: '5%'}}> <Head> <title>Content Management System</title> <link rel ="icon" href="/favion.ico"></link> </Head> <Navbar fixed="top" collapseOnSelect expand="lg" bg="dark" variant = "dark"> <Navbar.Brand href="/">CMS</Navbar.Brand> <Navbar.Toggle aria-controls="responsive-navbar-nav"></Navbar.Toggle> <Navbar.Collapse id="responsive-navbar-nav"> <Nav> <NavDropdown title="Sections" id="collasible-nav-dropdown"> <NavDropdown.Item href="/article">Articles</NavDropdown.Item> <NavDropdown.Divider/> <NavDropdown.Item href="/user">Users</NavDropdown.Item> </NavDropdown> </Nav> </Navbar.Collapse> </Navbar> </div> ); export default Header;
เราใช้ react-bootstrap สร้าง Nav และ Header ใหม่สำหรับไปแสดงร่วมกับหน้า index.js ดังนั้นเราจำเป็นต้องสร้าง _app.js (หรือบางที Project ของเราจะสร้างให้ ให้แก้ไขเอง) ใส่คำสั่งต่อไปนี้ใน _app.js
import 'bootstrap/dist/css/bootstrap.min.css'; import Header from './layouts/Header'; export default function MyApp({ Component, pageProps }) { return ( <> <Header /> <Component {...pageProps} /> </> ) }
ไป Render หน้าเว็บไซต์ใหม่ดูว่ามันแสดงผลแบบนี้ไหม:
เอาล่ะมาทำส่วนของ Firebase กัน ก่อนอื่นเราต้องไปที่ https://firebase.google.com ไปเปิดการใช้งานที่ Cloud Firestore
ตั้งค่า Rule เป็น Test Mode ก่อน
รันคำสั่งต่อไปนี้:
npm install firebase
เราจะทำงานร่วมกับ Firebase ได้แล้วไปสร้างไฟล์ชื่อว่า firebase.js ในโฟลเดอร์ “config” ใส่คำส่งต่อไปนี้
import firebase from 'firebase'; const firebaseConfig = { apiKey: "YOUR API KEY", authDomain: "YOUR AUTH DOMAIN", databaseURL: "YOUR DATABASE URL", projectId: "YOUR PROJECT ID ", storageBucket: "YOUR STORAGE BUCKET", messagingSenderId: "YOUR SENDER ID ", appId: "YOUR APP ID" }; try { firebase.initializeApp(firebaseConfig); } catch(err){ if (!/already exists/.test(err.message)) { console.error('Firebase initialization error', err.stack)} } const fire = firebase; export default fire;
ก็ไปเอาพวก apiKey, appId จากระบบของ Firebase กันเองนะครับ เราลองใส่ข้อมูลปลอมๆ ลงไปใน Firebase Cloud Firestore กันสัก 1 รายการ
ผมได้สร้าง Collection ชื่อว่า documents โดยเพิ่มรายการ title เข้าไปมีเนื้อหาว่า “ข้อมูลรายการที่ 1” ใน Cloud Firestore
ต่อมาให้ไปที่โฟลเดอร์ “components” ให้สร้างไฟล์ชื่อ GetData.js ขึ้นมาเขียนคำสั่งต่อไปนี้:
import { useState, useEffect } from 'react'; import firebase from '../config/firebase'; import Link from 'next/link'; const GetData = () => { const ref = firebase.firestore().collection('documents').doc(); const [collections, setBlogs] = useState([]); useEffect(() => { firebase.firestore() .collection('documents') .onSnapshot(snap => { const collections = snap.docs.map(doc => ({ id: doc.id, ...doc.data() })); setBlogs(collections); }); }, []); return ( <div> <table className='table table-striped'> <thead className='thead-dark'> <tr> <th scope="col">#</th> <th scope="col">Places</th> <th scope="col">Thumbnail</th> <th scope="col">Action</th> </tr> </thead> <tbody> {collections.map(document => <tr> <th scope="row">{document.id}</th> <td>{document.title}</td> <td>{document.thumbnail}</td> <td> <Link href="/content/[id]" as={'/content/' + document.id}> <a>Click</a> </Link> </td> </tr> )} </tbody> </table> </div> ) } export default GetData;
ก็คือมีการวนลูปส่วนของ references ของ collection ชื่อ “documents” ที่ผมใส่ไปใน
const ref = firebase.firestore().collection('documents').doc(); const [collections, setBlogs] = useState([]); useEffect(() => { firebase.firestore() .collection('documents') .onSnapshot(snap => { const collections = snap.docs.map(doc => ({ id: doc.id, ...doc.data() })); setBlogs(collections); }); }, []);
ส่วนการแสดงผลต้องมีการ import ส่วนของ Link มาใช้งาน
import Link from 'next/link';
ไปวนลูปและ Map ข้อมูลกับ HTML ใน <tbody> ตามคำสั่งนี้:
<tbody> {collections.map(document => <tr> <th scope="row">{document.id}</th> <td>{document.title}</td> <td>{document.thumbnail}</td> <td> <Link href="/content/[id]" as={'/content/' + document.id}> <a>Click</a> </Link> </td> </tr> )} </tbody>
ในส่วนของ Link จะวิ่งไปหาด้านในอีก Level โดยอ้างอิง id ของเอกสาร (Unique ID) ที่สร้างขึ้นดังนั้นต้องสร้าง Folder ชื่อ “content” ขึ้นมาและสร้างไฟล์ Javascript ชื่อว่า [id].js (ใช่ครับใส่ [] ด้วยเป็นชื่อไฟล์)
กลับไปที่ index.js เพิ่ม import บรรทัดบนสุด เรียกใช้ GetData ที่เราจะแสดงตาราง Table จาก Firebase
import GetData from '../components/GetData';
แล้วเพิ่ม ตาราง table นี้ใน <body>ของ index.js
<main style={{display: 'flex', flexDirection: 'column', alignItems:'center'}}> <h1>Content Management System</h1> <GetData /> </main>
ดังนั้น index.js จะเขียนแบบนี้:
import GetData from '../components/GetData'; const Index = () => ( <> <main style={{display: 'flex', flexDirection: 'column', alignItems:'center'}}> <h1>Content Management System</h1> <GetData /> </main> </> ) export default Index
แสดงผลหน้าแรกของเว็บไซต์จะเป็นดังนี้:
ไปที่ “content/[id].js” ให้เราเรียนคำสั่งในการอ่านข้อมูล แต่ละรายการโดยอ้างอิง parameter บน url ดังนี้:
import { useEffect, useState } from 'react'; import fire from '../../config/firebase'; import Link from 'next/link' const Content = (props) => { const [content, setContent] = useState(null); useEffect(() => { fire.firestore() .collection('documents') .doc(props.id) .get() .then(result => { setContent(result.data()) }) }, []); if(!content){ return( <h2>Loading...</h2> ) } return ( <div> <h2>{content.title}</h2> <p> {content.id} </p> <Link href="/"> <a>Back</a> </Link> </div> ) } Content.getInitialProps = ({ query }) => { return { id: query.id, } } export default Content
ถ้าโหลดหน้าเว็บจะมีคำสั่ง ปรากฏ
เมื่อโหลดเสร็จแล้วก็จะพบว่าเราเข้าถึงเนื้อหาใน Firebase Cloud Firestore ได้แล้ว
ตอนต่อไปจะทำฟังก์ชันในการกรอกข้อมูลเข้าไปจากหน้า Form ไปลง Cloud Fire Store ของ Firebase ครับ