react hooks的缺點(針對狀態不同步和沒有生命周期)


react在16.8中加入了hooks,可以在函數組件中添加一些有自己獨立上下文管理的狀態(useState),不再依賴於類組件,同時一些邏輯也可以放到hooks中來復用(useEffects)。

不巧,最近react項目里用到了hooks,就拿來練練手,在開發中遇到了點問題,我就說說我的問題和解決方案吧
1.沒有生命周期。
2.沒有回調函數。

缺點

一、狀態不同步
函數的運行是獨立的,每個函數都有一份獨立的作用域。函數的變量是保存在運行時的作用域里面,當我們有異步操作的時候,經常會碰到異步回調的變量引用是之前的,也就是舊的(這里也可以理解成閉包)如下:

import React, { useState } from "react";
​
const Counter = () => {
  const [counter, setCounter] = useState(0);
​
  const onAlertButtonClick = () => {
    setTimeout(() => {
      alert("Value: " + counter);
    }, 3000);
  };
​
  return (
    <div>
      <p>You clicked {counter} times.</p>
      <button onClick={() => setCounter(counter + 1)}>Click me</button>
      <button onClick={onAlertButtonClick}>
        Show me the value in 3 seconds
      </button>
    </div>
  );
};
​
export default Counter;

當你點擊Show me the value in 3 seconds的后,緊接着點擊Click me使得counter的值從0變成1。三秒后,定時器觸發,但alert出來的是0(舊值),但我希望的結果是當前的狀態1。
這時我們可以用useEffect來實現我們的需求

import React, { useState, useRef, useEffect } from "react";
​
const Counter = () => {
  const [counter, setCounter] = useState(0);
  const counterRef = useRef(counter);
​
  const onAlertButtonClick = () => {
    setTimeout(() => {
      alert("Value: " + counterRef.current);
    }, 3000);
  };
​
  useEffect(() => {
    counterRef.current = counter;
  });
​
  return (
    <div>
      <p>You clicked {counter} times.</p>
      <button onClick={() => setCounter(counter + 1)}>Click me</button>
      <button onClick={onAlertButtonClick}>
        Show me the value in 3 seconds
      </button>
    </div>
  );
};
​
export default Counter;

這時alert的是當前的值1。其實解決這個hooks的問題也可以參照類的instance。用useRef返回的immutable RefObject(current屬性是可變的)來保存state,然后取值方式從counter變成了: counterRef.current 。
二、沒有生命周期
比如我在開發中設置了個定時器,那我想頁面銷毀的時候肯定要清除定時器。那沒有生命周期的hooks怎么實現我們的需求呢。

 //創建一個標識,通用容器
    const timer = useRef(null);
    const onEvent = async (eventName, params) => {
        switch (eventName) {
            case 'updateFileList':
                try {
                    timer.current = setInterval(async () => {
                        await getReferenceBooKData(true, true, setAllocatedMainfestData);//某些循環請求數據的
                    }, 1500);
                } catch (e) {
                    // todo
                }
                return;
           
        }
    }
    useEffect(() => () => { return componentWillUnmount() }, []);
    //銷毀組件清除定時器
    const componentWillUnmount = ()=>{
        if (timer.current) {
            clearTimeout(timer.current);
        }
    };

代碼不是很全,主要可以參考方法的使用。就這樣完美解決了我的問題,相當於監聽了頁面銷毀的componentWillUnmount,如果你有其他需要周期需要操作的,也可以參考下面的用useEffect實現其他的周期變化操作

useEffect( () => console.log("mount"), [] );
useEffect( () => console.log("will update data1"), [ data1 ] );
useEffect( () => console.log("will update any") );
useEffect( () => () => console.log("will update data1 or unmount"), [ data1 ] );
useEffect( () => () => console.log("unmount"), [] );


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM