Skip to main content
0

สารจากผู้เขียน

มาลองเขียน Next.js กันเถอะ! ซึ่ง Version ที่เราใช้จะเป็นตัว 13.4.19 นะ ในบทความนี้เราจะมาสร้างโปรเจคที่ง่ายสุดๆ เพื่อให้เราเริ่มต้นกับ Next.js ได้อย่างรวดเร็ว โปรเจคนี้คือ “BMI Calculator” แบบเบสิก แล้วต้องเริ่มยังไง? ไปดูกันเลย!

เขียนโดย
Papatsiri Apipaiboon
Internship @ borntoDev

บทความนี้ตีพิมพ์ และ เผยแพร่เมื่อ 15 กันยายน 2566

เริ่มต้นกับ Next.js

แนะนำให้เริ่มแอป Next.js ใหม่โดยใช้ create-next-app บน command line ซึ่งจะตั้งค่าทุกอย่างให้เราโดยอัตโนมัติ ไม่จำเป็นต้อง npm install next ก่อน

npx create-next-app@latest

ในการติดตั้งก็จะมี prompt แสดงขึ้นมา และให้เราตั้งชื่อโปรเจค (Highlight คือ Choice ที่เลือกในโปรเจคนี้) 

What is your project named?...bmi-calculator-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias? No / Yes

 เสร็จแล้วก็เปิดเข้าไปดูโปรเจคได้เลย โครงสร้างโฟลเดอร์และไฟล์ต่างๆ ก็จะเป็นแบบนี้

เริ่มเขียนโค้ด

สร้างโฟลเดอร์ components ขึ้นมาใน app เพื่อที่จะได้เก็บ component ต่างๆ จากนั้นก็สร้างไฟล์ CardLayout ขึ้นมา

const CardLayout = ({ children }) => {
    return (
       <div className="w-full max-w-3xl overflow-hidden rounded-xl 
bg-[#FFFADD] shadow-lg">
        <div className="px-4 pyy-5 sm:p-6">{children}</div>
       </div>
    );
};

export default CardLayout;

ต่อไปก็สร้างไฟล์ BmiForm ในโฟลเดอร์ components สำหรับรับค่าน้ำหนักและส่วนสูงมาคำนวณหาค่าดัชนีมวลกาย (BMI) และประเมินว่าอยู่ในเกณฑ์ไหน ซึ่ง Next.js 13 ทุก component ที่สร้างใหม่จะมีค่า default เป็น server component แต่เราอยากแสดง BmiForm ให้ user interact ได้ด้วย React ก็ต้องเขียน ‘use client’ ไว้ด้านบนสุดเพื่อประกาศขอบเขตว่านี่คือ client component แล้วโมดูลหรือ child component อื่นๆ ที่ import เข้ามาในไฟล์นี้ก็จะถือเป็น client component โดยอัตโนมัติ จึงไม่จำเป็นต้องกำกับ ‘use client’ ไว้ที่ child component 

'use client';
import { useState, useEffect } from 'react';

import Height from './Height';
import Weight from './Weight';
import ResultCard from './ResultCard';

const BmiForm = () => {
    const [ height, setHeight ] = useState(0);
    const [ weight, setWeight ] = useState(0);
    const [bmi, setBmi] = useState(0);
    const [category, setCategory] = useState('');

    const handleReset = (e) => {
        e.preventDefault();
        setHeight(0);
        setWeight(0);
        setBmi(0); 
        setCategory(''); 
    };

    useEffect(() => {    
        if (height > 0 && weight > 0) {
            const calculatedBmi = (weight / ((height / 100) * (height / 
100))).toFixed(1);
            console.log('Calculated BMI:', calculatedBmi);
            setBmi(calculatedBmi);
    
            if (calculatedBmi < 18.5) {
                setCategory('Underweight');
            } else if (calculatedBmi >= 18.5 && calculatedBmi <= 24.9) {
                setCategory('Normal weight');
            } else if (calculatedBmi >= 25 && calculatedBmi <= 29.9) {
                setCategory('Overweight');
            } else if (calculatedBmi >= 30) {
                setCategory('Obesity');
            }
        } else {
            setBmi(0); 
            setCategory('-'); 
        }
    }, [height, weight]);
    

    return (
        <form className="mx-auto grid max-w-6xl gap-y-5 lg:grid-cols-2 lg:gap-x-8">
            <div className="flex flex-col gap-y-8 py-5 lg:px-5 lg:py-6">
                <Height height={height} setHeight={setHeight}/>
                <Weight weight={weight} setWeight={setWeight}/>
            </div>

            <ResultCard bmi={bmi} category={category} reset={handleReset}/>
        </form>
    );
};

export default BmiForm;

จากนั้นก็ไปเคลียร์ไฟล์ page แล้วแต่งหน้า Home ให้แสดง CardLayout กับ BmiForm ได้เลย

import CardLayout from '@/app/components/CardLayout'
import BmiForm from '@/app/components/BmiForm'

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-5 lg:p-24">
      <h1 className="my-14 text-center text-3xl font-bold uppercase 
tracking-widest">BMI Calculator</h1>
      <CardLayout>
        <BmiForm />
      </CardLayout>
    </main>
  );
}

แล้วก็อย่าลืมเคลียร์ไฟล์ global.css เพื่อปรับแต่ง style ใหม่ด้วยล่ะ

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  background: #FFCC70;
}

ต่อมาก็สร้างไฟล์ Height เป็น component สำหรับรับค่าส่วนสูง โดย height เป็นค่าส่วนสูงปัจจุบัน และ setHeight เป็นฟังก์ชันที่ใช้ในการเปลี่ยนค่าส่วนสูงเมื่อผู้ใช้กรอกข้อมูลในช่อง input

const Height = (props) => {
    const { height, setHeight } = props;
  
    return (
      <div>
        <label
          htmlFor="height"
          className="block font-serif text-lg font-light leading-6 text-gray-800"
        >
          Height
        </label>
  
        <div className="relative mt-2 rounded-md shadow-sm">
          <div className="pointer-events-none absolute inset-y-0 right-6 
flex items-center pl-3">
            <span className="text-gray-500 sm:text-sm">Cm</span>
          </div>
  
          <input
            type="number"
            name="height"
            id="height"
            className="block w-full rounded-md border-0 py-1.5 pl-5 pr-2 
text-gray-900 outline-none ring-1 ring-inset ring-gray-300 
placeholder:text-gray-400 focus:ring-2 focus:ring-inset 
focus:ring-cyan-500 sm:text-sm sm:leading-6"
            placeholder="0.00"
            aria-describedby="height"
            value={height}
            onChange={(e) => setHeight(e.target.value)}
          />
        </div>
      </div>
    );
  };
  
  export default Height;

ถัดมาเป็น component ไฟล์ชื่อ ResultCard เพื่อแสดงผลลัพธ์ค่า BMI และสรุปผลสุขภาพของผู้ใช้ว่าอยู่ในเกณฑ์ไหน ซึ่งมีการส่งค่า bmi, category, reset เข้ามาผ่าน props และมีการสร้างตัวแปร data ซึ่งเป็น Array ของ objects ในภาษา JavaScript โดยแต่ละ objects มีสอง key คือ label และ value และ objects แต่ละอันใช้เก็บข้อมูลที่ต้องการแสดงในส่วนต่างๆ จากนั้นก็ครอบ data.map(…) ใช้ในการ วนลูปผ่าน data เพื่อแสดงข้อมูลแต่ละส่วนที่มีใน ResultCard โดยแต่ละส่วนจะประกอบด้วยข้อความและค่าที่ถูกกำหนดใน data

cconst ResultCard = (props) => {
    const { bmi, category, reset } = props;

    const data = [
        {
            label: 'Your BMI is',
            value: bmi
        },
        {
            label: 'Result:',
            value: category
        }
    ];

    return(
        <div className="flex flex-col justify-between rounded-xl 
bg-[#FFC436] p-5 lg:py-10">
            <div className="flex flex-col gap-y-8">
                {data.map((item, i) => (
                    <div key={i} className="flex items-end justify-between">
                        <div>
                            <p className="text-[#3C4048] text-lg 
font-bold">{item.label}</p>      
                        </div>
                        <div className="flex items-baseline gap-x-2">
                            <span className="text-2xl font-bold text-[#3C4048]">
                                {item.value}
                            </span>
                        </div>
                    </div>
                ))}
            </div>

            <button
                type="submit"
                className="mt-14 w-full rounded-md bg-[#FFFADD] px-3.5 
py-2.5 text-lg font-semibold uppercase text-black shadow-sm 
hover:bg-cyan-100 focus-visible:outline focus-visible:outline-2 
focus-visible:outline-offset-4 focus-visible:outline-white"
                onClick={(e) => reset(e)}
            >
                Reset BMI
            </button>
        </div>
    );
};

export default ResultCard;

และนี่ก็คือหน้าตาโปรแกรม BMI Calculator ของเราที่เขียนด้วย Next.js เย้ๆๆ

ส่วนนี้คือโครงสร้างโฟลเดอร์หลังจากที่ทำเสร็จแล้ว

เป็นยังไงบ้างกับบทความนี้ เราได้เริ่มต้นเขียนโปรเจกต์ Next.js จากเริ่มต้น และทำแต่ละขั้นตอนเป็น step ไปเรื่อยๆ จนออกมาเป็นโปรเจกต์เล็กๆ ที่เบสิกและง่ายต่อการพัฒนาสุดๆ ทุกคนสามารถเริ่มต้นจากตรงนี้ และเพิ่มความซับซ้อนในโปรเจกต์ Next.js ขึ้นเรื่อยๆ ได้ตามต้องการเลย หวังว่าบทความนี้จะช่วยให้ทุกคนเริ่มต้นกับ Next.js ได้อย่างราบรื่นนะคะ!

ระบบฝึกทักษะ การเขียนโปรแกรม

ที่พร้อมตรวจผลงานคุณ 24 ชั่วโมง

  • โจทย์ปัญหากว่า 200 ข้อ ที่รอท้าทายคุณอยู่
  • รองรับ 9 ภาษาโปรแกรมหลัก ไม่ว่าจะ Java, Python, C ก็เขียนได้
  • ใช้งานได้ฟรี ! ครบ 20 ข้อขึ้นไป รับ Certificate ไปเลย !!
เข้าใช้งานระบบ DevLab ฟรี !เรียนรู้เพิ่มเติม

เรียนรู้ไอที “อัพสกิลเขียนโปรแกรม” จากตัวจริง
ปั้นให้คุณเป็น คนสายไอทีระดับมืออาชีพ

BorntoDev

Author BorntoDev

BorntoDev Co., Ltd.

More posts by BorntoDev
Close Menu

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

ตั้งค่าความเป็นส่วนตัว

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • คุกกี้ที่จำเป็น
    เปิดใช้งานตลอด

    ประเภทของคุกกี้มีความจำเป็นสำหรับการทำงานของเว็บไซต์ เพื่อให้คุณสามารถใช้ได้อย่างเป็นปกติ และเข้าชมเว็บไซต์ คุณไม่สามารถปิดการทำงานของคุกกี้นี้ในระบบเว็บไซต์ของเราได้
    รายละเอียดคุกกี้

  • คุกกี้สำหรับการติดตามทางการตลาด

    ประเภทของคุกกี้ที่มีความจำเป็นในการใช้งานเพื่อการวิเคราะห์ และ นำเสนอโปรโมชัน สินค้า รวมถึงหลักสูตรฟรี และ สิทธิพิเศษต่าง ๆ คุณสามารถเลือกปิดคุกกี้ประเภทนี้ได้โดยไม่ส่งผลต่อการทำงานหลัก เว้นแต่การนำเสนอโปรโมชันที่อาจไม่ตรงกับความต้องการ
    รายละเอียดคุกกี้

บันทึกการตั้งค่า