บทความและข่าวสาร | Seven Peaks Insights

การใช้งาน ReactJS Hooks และความสำคัญของการวางโครงสร้าง

เขียนโดย Seven Peaks - 10 มี.ค. 2021, 4:25:00

Error Boundary ใน ReactJS Hooks คืออะไร?

JavaScript ที่เป็นส่วนหนึ่งของ UI ไม่ควรทำให้แอปฯ ทั้งแอปฯ พัง ซึ่งใน React 16 นั้นมีคอนเซปต์ใหม่ที่เรียกว่า “error boundary” เพื่อแก้ไขปัญหานี้ให้กับผู้ใช้ของ ReactJS Hooks และ ReactJS state เมื่อดู code snippet ที่อยู่ตรงนี้ก็จะเห็นได้ว่ามันคือ React component อีกอันหนึ่งที่ตรวจจับ JavaScript error ที่อยู่ใน child component tree นั่นเอง แล้ว error ที่มันเจอเป็นแบบไหนกันนะ?

ที่จริงแล้ว มันคือ error ทุกอย่างที่เกี่ยวกับ UI นั่นแหละ ถ้าคุณเป็นโปรแกรมเมอร์ที่เขียนโค้ดในหลายๆ ภาษามาก่อน เช่น JavaScript คุณอาจจะคุ้นเคยกับ try/catch ซึ่งฟังก์ชันการ render ของ ReactJS นั้นเป็นแบบ declarative rendering ที่ยากต่อการจัดการกับ error ด้วย try/catch

error boundary ใช้เพื่อหา error ที่อาจเกิดขึ้นด้วยการใช้ try/catch เพื่อดักจับ UI error ทั้งหมดตอนที่กำลัง render อยู่, ใน constructor, และใน life-cycle method ได้ แต่ไม่สามารถตรวจเจอ error ได้ทุกรูปแบบ เช่น error ใน event handler, ใน sync code, ในโค้ดที่ render ไปยังฝั่งเซิร์ฟเวอร์, และแน่นอนว่ารวมถึง error ที่อยู่ใน error boundary component เองด้วย

ทำไมเราถึงจำเป็นต้องใช้มันด้วย?

ใน React 16 นั้น error ที่ไม่โดนดักจับด้วย error boundary ไหนเลยจะส่งผลให้เกิดการ unmount ทั้ง React tree
เหตุผลที่อยู่เบื้องหลังแนวคิดนี้ ได้แก่

– หยุด UI ที่พังไม่ให้แสดงผล
– ส่งฟีดแบ็กที่ดีขึ้นให้กับผู้ใช้เมื่อเกิด error ขึ้น
– เผยให้เห็นบั๊กที่ไม่ทันสังเกต

อย่างที่เราพูดถึงไปก่อนหน้านี้ว่ามันก็คือ React component อีกอันหนึ่ง การนำ error boundary ไปใช้นั้นสามารถทำได้ง่ายๆ ด้วยการเพิ่ม life-cycle function เหล่านี้เข้าไปใน class component ของคุณ

React Suspense คืออะไร?

อย่างที่ชื่อของมันบอกอยู่เป็นนัยๆ ว่ามันคือ React component ที่จะทำการหยุดการทำงานของ child component ทุกตัวจากการ render เมื่อมีตัวใดตัวหนึ่งไม่พร้อม ยกตัวอย่างเช่น โค้ดที่ทำงานแบบ dynamic loading หรือการ fetch ข้อมูล เป็นต้น จากนั้นจึงแสดง fallback component ขึ้นมาแทน

เมื่อ React Suspense และ ReactJS state เป็น built-in component อยู่ใน React พวกมันก็จะ render ตามปกติเหมือน component อื่นๆ หากดูที่ render tree จะเห็นว่าเมื่อ parent component ถูก render แล้ว child component ก็จะถูก render ตามไปด้วย

ในกรณีที่ child component ต้องดาวน์โหลดโค้ดหรือข้อมูลบางอย่าง เช่น asynchronous code เจ้า Suspense component จะถูกนำไปใช้เนื่องจาก child component ยังไม่พร้อมที่จะถูก render โดยมันจะโยน Suspense object กลับไปยัง parent component เพื่อหยุดพักการ render เนื่องจาก child component ยังไม่พร้อมใช้งาน

คุณสามารถใช้ React Suspense กับสิ่งต่อไปนี้ได้

  • ช่วยให้โหลด dynamic component พร้อมกับ React.Lazy ได้
  • ทำให้ไลบรารีสำหรับ fetch ข้อมูลสามารถ integrate กับ React ได้ลึกซึ้งมากยิ่งขึ้น
  • ทำให้คุณสามารถ orchestrate loading state ที่ออกแบบมาเพื่อใช้ด้วยกันได้
  • ช่วยให้คุณหลีกเลี่ยง race condition ได้

React-Query: คือไลบรารีจาก third-party ที่ทำให้ ReactJS และ ReactJS state สามารถบริหารจัดการ state สำหรับ asynchronous data ได้ทุกรูปแบบ การสร้าง query สามารถทำได้ด้วยการกำหนด unique key และฟังก์ชัน asynchronous เพื่อ resolve ข้อมูลด้วยพารามิเตอร์ของ useQuery

ReactJS Hooks คือฟีเจอร์ใหม่ใน React 16.8 ที่ทำให้คุณสามารถใช้ state และฟีเจอร์อื่นๆ ของ React ได้โดยไม่ต้องเขียนคลาสขึ้นมาใหม่

ทำไมต้องเป็น ReactJS Hooks ด้วย?

  • component ที่เรียบง่าย – ทำให้เขียนโค้ด component ได้ง่ายขึ้น
  • การนำ stateful logic มาใช้ใหม่ – Hook ช่วยให้คุณนำ logic ที่แตกต่างกันมาอยู่ในที่เดียวกันได้
  • คลาสเป็นสิ่งที่ชวนสับสน– เนื่องจากมันเป็น prototype-based inheritance ไม่ใช่ object-oriented inheritance

มันทำงานอย่างไร?

มี ReactJS Hooks API ให้ใช้ถึง 10 ตัว เช่น useState, useEffect, useContext, useCallback, และ useMemo นอกจากนี้ยังมีฟังก์ชันพื้นฐานอย่าง useState และ useEffect ให้ใช้งานด้วย

useState เป็น Hook ที่ทำให้คุณสามารถเพิ่ม ReactJS state ไปยัง functional component ที่เคยเป็นแบบ stateless ให้เป็น stateful ได้

useEffect คือ Hook ที่คุณสามารถใช้เพื่อบอก React ว่า component ของคุณต้องการทำอะไรบางอย่างหลังจากที่ render แล้ว ซึ่งมันจะถูก execute จาก 3 React component lifecycle ได้แก่ componentDidMount, componentDidUpdate, และ componentWillUnmount lifecycle

สรุปก็คือ ReactJS Hooks คือฟังก์ชันที่ทำให้คุณสามารถ ‘hook’ เข้าไปในฟีเจอร์ ReactJS state และ lifecycle จาก functional component ได้ พวกมันเป็น opt-in basis และรองรับเวอร์ชันเก่าได้ 100% ซึ่งประโยชน์หลักๆ ของ ReactJS Hooks คือการนำ stateful logic กลับมาใช้ใหม่

แม้ว่า Hooks จะเป็นสิ่งที่แทนที่คลาสได้ดีกว่า ในแง่ของ logic และ UI ที่สามารถแยกกันได้ง่าย แต่มันไม่ได้แทนที่ความเข้าใจของคุณเกี่ยวกับคอนเซปต์ของ React แต่อย่างใด เพราะมันคือการนำฟีเจอร์ที่มีอยู่มาใช้ในแนวทางที่แตกต่างออกไป หมายความว่าคุณยังต้องทำความคุ้นเคยกับคอนเซปต์พื้นฐานอย่าง props, state (ผ่านทาง ReactJS state), refs, และ lifecycle เพื่อใช้ฟีเจอร์เหล่านี้อยู่ดี

การคำนึงถึงโครงสร้างของโปรเจกต์

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

  • โครงสร้างโฟลเดอร์ – ความคุ้นเคยกับโปรเจกต์อาจส่งผลต่อประสิทธิภาพในการเขียนโค้ดของ developer ได้ ซึ่งคนที่เพิ่งเข้ามาร่วมโปรเจกต์อาจไม่คุ้นเคยกับโครงสร้างโฟลเดอร์
  • ความคุ้นเคยกับเครื่องมือที่ใช้ – เนื่องจาก React คือไลบรารีเดียวที่ต้องการเครื่องมืออื่นอีกมากมายในการรองรับการใช้งาน เช่น redux-thunk, redux-saga, formik, react-hook-form, และ react-query
  • คนดูแลโปรเจกต์หรือสมาชิกใหม่ – เป็นเรื่องธรรมดาที่โปรเจกต์อาจจะใช้เวลานานในการปรับเปลี่ยนหรือเพิ่มคนดูแลโปรเจกต์ใหม่เข้ามา ซึ่งคนใหม่ที่เข้ามาก็อาจจะไม่ค่อยมีข้อมูลเกี่ยวกับโปรเจกต์มากนัก
  • เอกสารคู่มือ – การที่ developer จะหาโค้ดสำหรับฟีเจอร์ที่ต้องการได้นั้นอาจเป็นเรื่องยาก เพราะแต่ละโปรดักต์ก็มีฟีเจอร์ที่แตกต่างกัน

ภาพรวมของโปรเจกต์ คือ สิ่งที่คุณจะได้เห็นเมื่อเริ่มต้นโปรเจกต์ใหม่ขึ้นมา

component คือสิ่งที่เป็นอิสระจากส่วนอื่นและเป็นโค้ดชุดหนึ่งที่เน้นเรื่องของ UI ซึ่งสามารถนำกลับมาใช้ใหม่ได้

คุณจะมองมันเป็นเหมือนกับชุดบล็อกตัวต่อก็ได้ ซึ่ง component แบ่งออกเป็นสองประเภท ได้แก่ คลาส และ ฟังก์ชัน

API ทำให้เกิดการโต้ตอบระหว่างซอฟต์แวร์หนึ่งกับอีกซอฟต์แวร์หนึ่ง

container นั้นสนใจแค่การบริหารจัดการข้อมูล ไม่ใช่ UI

Hooks, Hocs, Context – Hook ทำให้คุณสามารถใช้งาน ReactJS state กับฟีเจอร์อื่นๆ ของ React ได้โดยไม่ต้องเขียนคลาส ส่วน higher-order component (HOC) คือเทคนิคขั้นสูงใน React สำหรับการนำ component logic กลับมาใช้ใหม่ ส่วน Context นั้นได้รับการออกแบบมาเพื่อแชร์ข้อมูลที่นับว่าเป็น “global” สำหรับ tree ที่มี component ของ React และ ReactJS state ได้

  • Helpers
  • Utilities
  • Testing
  • Store
  • Translations
  • Assets
  • Styles
  • Pages
  • Constants
  • Layouts
  • Router
  • Storybook
  • Types

คุณควรวางโครงสร้างโฟลเดอร์ของโปรเจกต์อย่างไร?

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

แบบทั่วไป: สร้างศูนย์รวมข้อมูลที่เก็บข้อมูลทุกอย่างเอาไว้ในที่เดียว ไม่ว่าคุณจะต้องการอะไรก็หาเจอ

แบบเน้นฟีเจอร์: โครงสร้างทั้งหมดขึ้นอยู่กับฟีเจอร์และไม่ได้พึ่งพากัน รูปแบบนี้นำไปใช้บ่อยสำหรับฟีเจอร์ของโปรดักต์

สรุปทิ้งท้าย

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

การปรับขนาด: การเพิ่มฟีเจอร์ใหม่เข้าไป type จะไม่แตกต่างกันมาก จึงจำเป็นต้องใส่เข้าไปในหลายๆ โฟลเดอร์แบบทั่วไป ส่วนแบบเน้นฟีเจอร์ คุณอาจจะต้องเพิ่มเข้าไปแค่ในโฟลเดอร์ของฟีเจอร์ที่ต้องการ implement เท่านั้น

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

ทีมงาน senior frontend developer ของเรา มีความเชี่ยวชาญด้านการพัฒนาเว็บไซต์ให้ทันสมัยด้วยเฟรมเวิร์ก JavaScript ที่ได้รับการยอมรับอย่าง React native และ ReactJS

ดูตัวอย่างโค้ดของ ReactJS Hooks, ReactJS state และอื่นๆ ได้ใน วิดีโอแบบเต็มๆ ของเราบน YouTube