เมื่อผมเริ่มเขียน React ได้ 3 เดือน จาก Class Component เป็น Functional Component ด้วย HOCs กับ Recompose
ต้องเกริ่นไว้ก่อนที่ว่า บทความนี้เป็นอันแรก ยังไงก็ฝากเนื้อฝากตัวด้วยครับ
การทำงานส่วนตัวผู้เขียน ผมเองเคยมีพื้นฐานการทำ Product ที่เป็น App และ Components จาก Javascript และ Frameworks ค่าย Google หลายตัว อาทิ AngularJS1, 2–4 & PolymerJS เป็นต้น ในช่วงต้นปี 2018 ได้มีโอกาสพัฒนา App ตัวใหม่ด้วย Framework จากค่าย Facebook ทำให้ผมเริ่มเข้ามารู้จักกับ React
เข้าเรื่องกันเลยดีกว่าครับ
ก่อนอื่นเราต้องรู้จัก Class Components และ Functional Components
- Class Components
เป็นวิธีการสร้าง component แบบดั้งเดิมแต่แรกเริ่มด้วย Class กับ Syntax มาตรฐานที่ต้องทำก็คือนำไป extends ด้วย React.Component จากนั้นก็ setState และ ใส่ DOM ลงใน render() เพื่อให้ React นำไปจัดการให้เรา
class Hello extends React.Component {
state = { name: '' }; componentDidMount() {
this.setState({ name : 'world' });
} render() {
return (<div>Hello ${this.state.name}!</div>);
}}
- Functional Components
คนที่ใช้ Javascript ES6 ด้วยการสร้าง Function ใส่ input ต่อไปด้วยการ destructure และ return เป็นหน้าตาแบบ curly braces ก็จะออกมาเป็น component ให้เราใช้งานได้ง่ายๆ เลย
const Loading = ({count}) => (<div>`..loading in ${count}`);
HOCs กับ Recompose คืออะไร ?
- Higher-Order Components(HOCs) คืออะไร ?
ตอบง่ายๆก็คือ Function ที่รับ Components แล้วแปลงให้เป็น Component ใหม่นั่นเอง - Recompose เป็น Library ตัวนึงที่ช่วยให้เราทำ HOCs ของตัวเองขึ้นมา แล้วนำไปใช้งานกับ React Component
ไหนลองแปลงร่าง Class Components เป็น Functional Components
ผมได้หยิบ Tutorial ของ การสร้าง Bitcoin Chart App ที่ไว้ดูราคาปิดของ Bitcoin ด้วย React & VX มาเป็นตัวอย่างที่จะใช้ทดลองทำเป็น Functional Components
Bitcoin Chart — Class Component Version(Tutorial Version)
Code ตัวอย่างจาก Tutorial ด้านบน การเขียน React โดยปกติแล้วก็ เราจะต้องเขียน App.js ที่มี Class Components และมี behavior ตาม lifecycle ที่จะไปทำการ fetch data ตามลำดับ รวมถึงการ setState เพื่อนำ data ไปแปลงเป็น scale สำหรับการวาดด้วย VX และการสร้าง Handler event ต่างๆ ซึ่งส่วนตัวแล้วผมมองว่า ลำดับหน้าที่ค่อนข้างสับสนวุ่นวาย สำหรับสิ่งที่จะเอาไปใช้ในตัว render ของ App เดี๊ยวเราจะไปแปลง Code ชุดนี้ให้เป็น Functional Components กัน
ปล.ถ้าสังเกตดีๆ withTooltip ก็จะเป็น HOCs ตัวหนึ่งที่ทาง Tutorial เค้าเอามาใช้
Bitcoin Chart — Functional Component Version
การแปลง Code ครั้งนี้จะสังเกตให้เห็นว่า App ถูกแปลงด้วยการใช้ Functional Components จะทำให้การแบ่งหน้าที่ของแต่ละสิ่งชัดเจนยิ่งขึ้น และแยกออกจากกันรวมถึงการนำไปสร้างหรือไปใช้ต่อกับ Components อื่นๆได้ง่ายยิ่งขึ้น รวมถึงการคำนึงถึงลำดับการรับ props คือสิ่งสำคัญในการ compositions สำหรับ HOCs
สิ่งที่ขาดไปไม่ได้เลยก็คือ Recompose Helpers เพื่อสร้าง HOCs ดังต่อไปนี้
- withState ใช้เพื่อสร้าง state รวมทั้ง set state และกำหนด default value
- withHandlers ทำให้เราสามารถสร้าง custom handler จากสิ่งที่ได้รับจาก props และ event เมื่อ handlers ตัวนั้นถูก invoke callback
- lifecycle ใช้ในจังหวะการ setup state เช่น fetch เพื่อดึงข้อมูล สามารถใช้ประโยชน์ได้หลากหลายรูปแบบ เช่น add/remove event listeners เป็นต้น
- branch & renderComponent สองตัวนี้เราสามารถใช้ด้วยกันเพื่อทำ Conditional component ตัวอย่างก็คือการให้ Loading Component โชว์ขึ้นมากก่อนที่ data จะ resolve กลับมาหลังจากการ fetch
- withProps ใช้สร้าง props ใหม่และ merge สิ่งใหม่กลับเข้าไป
- onlyUpdateForKeys ช่วยให้ performance ของเราดีขึ้นเพื่อ update props เฉพาะที่เราสนใจ เพราะการเปลี่ยนค่า props อาจจะกระทบต่อการสร้าง Component ขึ้นมาใหม่โดยไม่จำเป็น ดังนั้นการที่เราสนใจแค่บางตัว React จะรู้ว่า props ตัวไหนควร update และ สร้าง Component ขึ้นมาใหม่ อย่างเช่น tooltipData ที่เปลี่ยนทุกครั้งที่มี event ของ mouse เป็นต้น
ทดสอบ Functional Component Version กันหน่อย
ที่ทำมาแชร์กันในส่วนนี้ก็อยากให้มองว่าเป็นฝากให้มองเป็น Concept เพื่อนำไปพัฒนาต่อยอดการเขียน React ถ้าผิดพลาดประการใดขออภัยด้วยครับ ขอบคุณครับ