วิธีการตั้งค่า React Context
Prop drilling ทำให้โค้ดของคุณพัง คุณต้องส่งข้อมูลผ่านคอมโพเนนต์ถึงห้าชั้นทั้งที่พวกมันไม่จำเป็นต้องใช้เลย React Context ช่วยแก้ปัญหานี้ได้ แต่การตั้งค่าส่วนใหญ่มักจะสร้างปัญหาใหม่ขึ้นมาแทน
เมื่อคุณใช้ "Go to Definition" กับ context hook คุณมักจะไปโผล่ในไฟล์ที่มีเพียงแค่การเรียกใช้ useContext สั้นๆ เท่านั้น แต่ตรรกะ (logic) จริงๆ กลับอยู่ในอีกไฟล์หนึ่ง ทำให้คุณต้องเสียเวลาทั้งวันเพื่อตามหา state logic
คุณสามารถแก้ไขปัญหานี้ได้ด้วยการวางโครงสร้างที่ดีกว่าเดิม
ทำตามรูปแบบนี้:
- รวม context, public hook และ state logic ไว้ในไฟล์เดียวกัน
- ให้ Provider เป็นเพียง thin shell
- ใช้ lint rule เพื่อป้องกัน private logic ของคุณ
จัดโครงสร้างไฟล์ของคุณดังนี้:
src/context/ • GameContext.ts (Context, public hook และ state logic) • GameProvider.tsx (A thin shell)
ภายใน GameContext.ts ให้สร้างสามส่วนดังนี้:
- The context object
- A public hook สำหรับให้คอมโพเนนต์ใช้งาน โดย hook นี้ควรจะ throw error หาก context เป็น null เพื่อให้มั่นใจว่าคอมโพเนนต์ของคุณจะแจ้งข้อผิดพลาดทันที (fail fast) หากอยู่นอก provider
- A private hook สำหรับการจัดการ state ซึ่ง hook นี้จะบรรจุการเรียกใช้
useStateหรือuseReducerของคุณไว้
การรวม public hook และ private logic ไว้ในไฟล์เดียวกันจะทำให้ "Go to Definition" ทำงานได้อย่างสมบูรณ์แบบ คุณสามารถกระโดดจากคอมโพเนนต์ไปยัง logic ได้โดยตรง
อย่างไรก็ตาม ยังมีความเสี่ยงหนึ่งอยู่ เนื่องจากเราต้อง export private hook เพื่อให้ Provider สามารถใช้งานได้ เพื่อนร่วมทีมอาจจะเผลอไปเรียกใช้มันในที่ที่ไม่ควรใช้ ซึ่งจะทำให้เกิด state ใหม่ที่แยกเป็นเอกเทศ แทนที่จะเป็นการใช้ shared context ร่วมกัน
เลิกใช้คอมเมนต์เพื่อป้องกันเรื่องนี้ แต่ให้ใช้ ESLint rule แทน
ผมได้สร้าง eslint-plugin-restrict-callers ขึ้นมาเพื่อแก้ปัญหานี้ โดยคุณสามารถกำหนดได้ว่าฟังก์ชันใดบ้างที่ได้รับอนุญาตให้เรียกใช้ hook เฉพาะเจาะจงได้
ตัวอย่างเช่น คุณสามารถบอก ESLint ว่ามีเพียง GameProvider เท่านั้นที่สามารถเรียกใช้ useGameStateManagement ได้ หากมีคนอื่นพยายามเรียกใช้ การ build จะล้มเหลวพร้อมข้อความแจ้งข้อผิดพลาดที่ชัดเจน
สรุปขั้นตอนการทำงาน:
- รวม context, public hooks และ private logic ไว้ในไฟล์เดียว
- ใช้ Provider เพียงเพื่อส่งผลลัพธ์จาก hook ไปยัง provider value เท่านั้น
- Throw error ใน public hook หากไม่พบ context
- ใช้ ESLint เพื่อกำหนดขอบเขตระหว่าง public hook และ private hook
Source: https://dev.to/jareddlewis/how-to-set-up-react-context-2c9h
