自公司前後分離上手React以來,一個坑一個坑的踩,Class的全生命週期雲裡霧裡,還麼屢明白,就抱上了Hook的大腿不鬆手,確實爽到飛起。修改到Hook的過程基本比較順暢,直接少了三分之一的程式碼,元件更容易封裝,除錯更方便,諸多優點在此不再贅述,已有各路大佬紛紛評價,此處貼上中文官方地址:React-Hook文件。這裡主要講講修改到一塊關於 Unity 3D模型載入的踩坑記。
背景:React 載入 Unity 3D模型 ,使用到一個外掛 react-unity-webgl,感興趣的盆友可以自行查閱。
因為Class改Hook處理語法變動,邏輯程式碼基本不用怎麼改動,所以基本沒有阻力,但是當我把這塊業務程式碼改成Hook時,跟模型互動時通訊失敗,無法驅動模型動作。百思不得其解,弄了倆測試頁面,test_hook、test_class,只能debugger,一步一步調,發現一些端倪。
Class 有些初始化的程式碼 都寫在了constructor(props){},這個大家都明白,第一次載入頁面的時候會走。hook呢,最外層是一個大方法,之前遷移的時候就寫在方法裡最頂部了,也沒什麼問題。載入模型第一句是 const unityContent = new UnityContent(引數1,引數2);兩個頁面都能載入出來模型,但是跟斷點發現hook頁面的 unityContent 物件比class的缺少了一個重要的屬性:unityInstance,通訊的方法就是靠它 Send() 的,而且發現同一個物件,屬性id一直在變,原來每次修改state時,都會走宣告的這段方法,導致每次都 new 一個新的物件,導致unityInstance屬性沒有正確掛在unityContent物件上。
在知道大概原理的情況下,搞成全域性變數,在載入時判斷是否已經初始化,問題就迎刃而解了(其實費了九牛二虎之力)。
寫過hook的盆友第一反應會想到宣告寫到useEffect,然後 [] 只執行一次才是正確的寫法。
之所以沒有呢,是因為模型載入跟其他的業務沒什麼關係,我並不需要渲染完整個DOM在來載入,並且載入模型很費時間,必須要剛載入頁面就同時載入模型,所以才有此次踩坑記。
總結:Hook寫在useEffect之外的程式碼會多次載入(包括重新整理狀態),要做好判斷,否則很容易產生bug。更推薦(官方推薦)按業務按順序把初始化方法寫到useEffect。