วิธีการแก้ไขปัญหา Asynchronous Function บน React.js Hook (useEfffect) ด้วยวิธี IIFE

React.js Mar 29, 2023

เกริ่นก่อนว่า บทความนี้จะเป็นบทความสั้นๆ เพื่อบันทึกการแก้ไขปัญหาในกรณี โดยก่อนหน้านี้ ผมได้มีประสบการณ์เกี่ยวกับการใช้งาน Asynchronous Function จำพวก Promise() ภายใน useEffect ซึ่งเป็น React.js Hook เพื่อเรียกข้อมูลจาก APIs มาเก็บไว้ใน State

ยกตัวอย่างจากโค้ดข้างล่างนี้ เป็นการสร้างฟังก์ชั่นขึ้นมาหนึ่งอัน การทำงานคือ เรียกใช้ฟังก์ชั่น fetch() ซึ่งเป็นหนึ่งใน Native Javascript Promise Function เพื่อเรียกข้อมูลจาก APIs ผ่าน HTTP Request ทั่วๆไป และคาย Response ออกมาเป็น Json Object

const [data, setData] = useState()
const getDataFromAPI = async () => {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    await fetch(`${process.env.REACT_APP_CUSTOM_API}`, {
      method: 'GET',
      headers: myHeaders,
    })
      .then(response => response.json())
      .then(response => setData(response))
      .catch((error) => {
        console.error('Error:', error);
      })
  }

จากนั้น เราต้องการเรียกใช้ฟังก์ชั่นดังกล่าว เพื่อเก็บข้อมูลเอาไว้ที่ State เราก็จะให้ฟังก์ชั่นมันทำงานเมื่อมีการ Render โดย React Hook Function คือ useEffect()

แต่ fetch เป็นการทำงานแบบ asynchronous จึงต้องการใช้ async await มาช่วยเพื่อเรียกข้อมูลผ่านreturn ของ callback function ดังนั้น การใช้งานบน useEffect() จึงน่าจะเป็นประมาณนี้

React.useEffect(async() => {
	await getDataFromAPI();
}, []);

แต่เมื่อลอง Render ดูแล้ว พบว่า การทำงาน เกิด Error ขึ้นบน console แบบนี้

TypeError: func.apply is not a function

เมื่อลองหาวิธีแก้ปัญหาดู จึงค้นพบว่า useEffect() จะทำงานได้ตามปกติ กับฟังก์ชั่นที่ไม่ใช่ Asynchronous ดังนั้นมันจึงมองว่า getDataFromAPI() ไม่ใช่ฟังก์ชั่น แนวทางการแก้ปัญหาคือ ต้องให้มันทำงานภายในฟังก์ชั่นอื่นก่อน โดยใช้ IIFE

IIFE ย่อมาจาก Immediately Invoked Function Expression เป็นฟังก์ชั่นหนึ่งที่มีคุณสมบัติในการรันทันทีที่ถูกสร้างขึ้นมา รูปแบบการสร้างเป็นแบบนี้

(function () {
  // …
})();

(() => {
  // …
})();

(async () => {
  // …
})();

ดังนั้น เราจึงเปลี่ยน useEffect() ให้เป็นแบบนี้แทน

React.useEffect(() => {
	(async () => {
		await getDataFromAPI();
	})()
}, []);

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

อ้างอิง
https://stackoverflow.com/questions/63570597/typeerror-func-apply-is-not-a-function
https://developer.mozilla.org/en-US/docs/Glossary/IIFE
https://rapidapi.com/guides/fetch-api-async-await


ช่วงขายของ

ตอนนี้เรามีบริการรับทำเว็บไซต์เพื่อจุดประสงค์ต่างๆ เช่น
- ร้านค้าออนไลน์
- โปรโมทบริษัท
- เว็บบล็อกสำหรับเขียนบทความ
- หน้าขายของแบบหน้าเดียว (Single Page)
และอื่นๆ โดยใช้ Wordpress เป็นโครงสร้างหลังบ้านและหน้าบ้าน ทำให้ดูแลรักษาง่ายในระยะยาว
คุณไม่ต้องมีแบบมาก่อน ไม่เป็นไร เรามีหน้าเว็บตัวอย่างมาให้คุณเลือกหลายสิบแบบ ราคาคุ้มค่า และส่งมอบงานไว สามารถเข้ามาดูรายละเอียด และสอบถาม-พูดคุยได้ที่เว็บไซต์ของ OneFastWeb ได้เลยครับ ขอบคุณครับ


Tags