DEV Community

Siwakorn Sittilerdpaisal
Siwakorn Sittilerdpaisal

Posted on

[React]: Core concept

Pure Function

Pure function เป็น function ที่มีคุณสมบัติสำคัญ 2 ประการ คือ

1. No Side Effect: ฟังก์ชันจะไม่เปลี่ยนแปลงค่าภายนอกหรือมีผลข้างเคียงใด ๆ กับโปรแกรม เช่น ไม่เปลี่ยนแปลงค่าของตัวแปร global, ไม่เขียนข้อมูลลงไฟล์ หรือส่งผลกระทบต่อฐานข้อมูล

2. Deterministic: ฟังก์ชันจะคืนค่า (return)

output เหมือนเดิมเสมอเมื่อได้รับ input ที่เหมือนเดิม

กล่าวอีกนัยหนึ่งคือ ฟังก์ชันจะต้องมีพฤติกรรมที่คาดเดาได้

Example: Pure function

function add(a: number, b: number): number {
    return a + b;
}
Enter fullscreen mode Exit fullscreen mode

ในตัวอย่างนี้ function add เป็น Pure function เนื่องจาก:

  1. ผลลัพธ์ของฟังก์ชันจะขึ้นอยู่กับ input a และ b เท่านั้น โดยไม่มีการเปลี่ยนแปลง state ภายนอก
  2. เมื่อใส่ค่าเดียวกัน เช่น add(2, 3) ทุกครั้งที่เรียกฟังก์ชันนี้จะได้ผลลัพธ์เป็น 5 เสมอ

Example: Impure function

let count = 0;

function increment(): number {
    count += 1;
    return count;
}
Enter fullscreen mode Exit fullscreen mode

ในตัวอย่างนี้ increment เป็น Impure function เนื่องจาก:

  1. มีการเปลี่ยนแปลง state ภายนอก (ตัวแปร count)
  2. ผลลัพธ์ของฟังก์ชันไม่สามารถคาดเดาได้เสมอไป ถ้าเรียก increment() หลายครั้ง จะได้ผลลัพธ์ที่แตกต่างกัน เช่น ครั้งแรกได้ 1 ครั้งถัดไปอาจได้ 2, 3, เป็นต้น
function addRandomToNumber(num: number): number {
    const randomValue = Math.random(); // ค่า random ไม่สามารถควบคุมได้
    return num + randomValue;
}

ในตัวอย่างนี้ **addRandomToNumber** เป็น Impure function เนื่องจาก:

const result = addRandomToNumber(5); // ผลลัพธ์จะเปลี่ยนไปทุกครั้งที่เรียกใช้
Enter fullscreen mode Exit fullscreen mode

ในกรณีนี้ addRandomToNumber เป็น Impure function เช่นกัน เนื่องจาก

  1. ฟังก์ชัน Math.random() ทำให้ค่าที่ส่งออกมาไม่สามารถคาดเดาได้ แม้ว่า input (num) จะเป็นค่าคงที่ เช่น 5 ผลลัพท์อาจจะออกมาเป็น 5.1 หรือ 5.82

Memoization

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

ตัวอย่างการใช้งาน Memoization

  1. ฟังก์ชัน Fibonacci แบบไม่ใช้ Memoization
function fibonacci(n: number): number {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}
Enter fullscreen mode Exit fullscreen mode

ในกรณีนี้ การคำนวณ Fibonacci แบบ recursive ทำให้เกิดการเรียกฟังก์ชันซ้ำ ๆ กันมากมาย ส่งผลให้เกิดการคำนวณซ้ำซ้อน และทำให้โปรแกรมทำงานช้าลง

  1. ฟังก์ชัน Fibonacci แบบใช้ Memoization
function memoizedFibonacci(): (n: number) => number {
    const cache: { [key: number]: number } = {};

    return function fib(n: number): number {
        if (n in cache) {
            return cache[n]; // คืนค่าจาก cache ถ้ามีอยู่
        }

        if (n <= 1) {
            return n;
        }

        const result = fib(n - 1) + fib(n - 2);
        cache[n] = result;  // บันทึกผลลัพธ์ใน cache
        return result;
    };
}
Enter fullscreen mode Exit fullscreen mode

First-Class Functions

ทำให้ภาษาสามารถจัดการกับ function ได้เหมือนข้อมูลทั่วไป

1. การเก็บฟังก์ชันในตัวแปร

// เก็บฟังก์ชันในตัวแปร
const greet = function(name: string): string {
    return `Hello, ${name}!`;
};
Enter fullscreen mode Exit fullscreen mode

2. การส่งผ่านฟังก์ชันเป็นพารามิเตอร์

function greet(name: string): string {
    return `Hello, ${name}!`;
}

function printMessage(func: (name: string) => string, name: string): void {
    console.log(func(name));
}
Enter fullscreen mode Exit fullscreen mode

3. การคืนค่าฟังก์ชันจากฟังก์ชัน

function createGreeting(greeting: string) {
    return function(name: string): string {
        return `${greeting}, ${name}!`;
    };
}
Enter fullscreen mode Exit fullscreen mode

4. การใช้ฟังก์ชันภายในโครงสร้างข้อมูล

const operations = {
    add: (a: number, b: number) => a + b,
    subtract: (a: number, b: number) => a - b,
    multiply: (a: number, b: number) => a * b,
    divide: (a: number, b: number) => a / b
};
Enter fullscreen mode Exit fullscreen mode

Immutable

คือ ข้อมูลหรือค่าที่ไม่สามารถเปลี่ยนแปลงได้หลังจากที่ถูกสร้างขึ้นมาแล้ว ในการเขียนโค้ดแบบ Immutable ทุกครั้งที่ต้องการเปลี่ยนแปลงข้อมูล จะต้องสร้างข้อมูลใหม่ขึ้นมาแทนการแก้ไขข้อมูลเดิม

ประโยขน์

1. Prevent Side Effects: เนื่องจากข้อมูลไม่ถูกเปลี่ยนแปลงโดยไม่ตั้งใจ โปรแกรมสามารถทำงานได้อย่างน่าเชื่อถือมากขึ้น
2. Traceable: การติดตามการเปลี่ยนแปลงของข้อมูลทำได้ง่ายขึ้น เพราะข้อมูลไม่ถูกแก้ไข
3. Race Conditions: การใช้ข้อมูลแบบ Immutable ช่วยป้องกันปัญหาที่เกิดจากการแก้ไขข้อมูลพร้อมกัน

Object

Example: Mutable

const person = { name: "Alice", age: 25 };
person.name = "Bob"
Enter fullscreen mode Exit fullscreen mode

Example: Immutable

const person = { name: "Alice", age: 25 };

// สร้างออบเจ็กต์ใหม่ โดยไม่เปลี่ยนแปลงข้อมูลเดิม
const updatedPerson = { ...person, age: 26 };
const updatedPerson2 = Object.assign(person, { age: 28 })
Enter fullscreen mode Exit fullscreen mode

Primitive data type

  • number
  • bigint
  • string
  • boolean
  • null
  • undefined
  • symbol

ทั้งหมดเป็น Immutable เมื่อเราทำการสร้างค่าขึ้นใหม่จากค่าที่มีอยู่แล้ว การเปลี่ยนแปลงค่าในตัวแปรจะส่งผลให้มีการสร้างค่าใหม่แทนที่จะเปลี่ยนแปลงค่าดั้งเดิม

Array

Example: Mutable

const arr = [1, 2, 3];
arr.push(4);  // เปลี่ยนแปลงข้อมูลใน arr
console.log(arr); // [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

Example: Immutable

const arr = [1, 2, 3];

// สร้างอาร์เรย์ใหม่แทนการแก้ไขของเดิม
const newArr = [...arr, 4]; 
Enter fullscreen mode Exit fullscreen mode

Solution

Operation avoid(mutate) prefer (new array)
adding push, unshift concat, [...arr]
removing pop, shift, splice filter, slice
replacing splice, arr[i] = ... map
sorting reverse, sort [...arr].sort()

Thinking in React

*1. แบ่ง UI ออกเป็น Component
*

Image description

  1. FilterableProductTable: (สีเทา): container ของหน้านี้
  2. SearchBar (สีน้ำเงิน): รับข้อมูลจาก user เพื่อกรองข้อมูล
  3. ProductTable (สีม่วง): แสดง list ของข้อมูลสินค้า
  4. ProductCategoryRow (สีเขียว): แสดงข้อมูลกลุ่มของสินค้า
  5. ProductRow (สีเหลือง): แสดงข้อมูลของสินค้า

2. Create Static UI

Props กับ State

1. Props คือ ข้อมูลที่ parent component ส่งให้กับ child component เพื่อปรับแต่งลักษณะการแสดงผลได้ เช่น form สามารถส่ง props สีไปยังปุ่ม button ได้

2. State คือ เปรียบเสมือนหน่วยความจำของคอมโพเนนต์ โดยช่วยให้คอมโพเนนต์ติดตามข้อมูลบางอย่างและเปลี่ยนแปลงได้ตามการโต้ตอบของผู้ใช้ เช่น ปุ่ม Button อาจติดตาม state ที่บ่งบอกสถานะการชี้เมาส์ (isHovered) State is reserved only for interactivity

Props และ State นั้นแตกต่างกัน แต่ทำงานร่วมกันได้ดี parent component จะเก็บข้อมูลบางอย่างใน state (เพื่อให้สามารถเปลี่ยนแปลงได้) แล้วส่งข้อมูลเหล่านั้นไปยังคอมโพเนนต์ลูกในรูปแบบของ props

Top comments (0)