日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React?useCallback使用教程_React

作者:折桂懷橘 ? 更新時間: 2023-02-14 編程語言

開始之前請注意這句話:任何優化都會增加復雜性,任何過早添加的優化都會帶來風險,因為優化后的代碼可能會多次更改

useEffect

相關作用:監聽 & 初始化

//最簡單用法
   useEffect(() => {
     //只有方法體,相當于componentDidMount和componentDidUpdate中的代碼
    document.title = count;
  })
  //加返回值用法
  useEffect(() => {
    //添加監聽事件,相當于componentDidMount和componentDidUpdate中的代碼
    window.addEventListener('resize', onChange, false);
    //返回的函數用于解綁事件,相當于componentWillUnmount中的代碼
    return () => {
      window.removeEventListener('resize', onChange, false)
    }
  })
  //加空數組參數用法
  useEffect(() => {
    // 相當于 componentDidMount
    window.addEventListener('resize', onChange, false)
    return () => {
      // 相當于 componentWillUnmount
      window.removeEventListener('resize', onChange, false)
    }
  }, []);
  //加監聽值用法
  useEffect(() => {
   //只有當count的值發生變化,此函數才會執行
    console.log(`count change: count is ${count}`)
  }, [ count ]);

useCallback

先看一個最簡單的例子:

// 用于記錄 getData 調用次數
let count = 0;
function App() {
  const [val, setVal] = useState("");
  function getData() {
    setTimeout(()=>{
      setVal('new data '+count);
      count++;
    }, 500)
  }
  useEffect(()=>{
    getData();
  }, []);
  return (
    <div>{val}</div>
  );}

getData模擬發起網絡請求。在這種場景下,沒有useCallback什么事,組件本身是高內聚的。

如果涉及到組件通訊,情況就不一樣了:

// 用于記錄 getData 調用次數
let count = 0;
function App() {
  const [val, setVal] = useState("");
  function getData() {
    setTimeout(() => {
      setVal("new data " + count);
      count++;
    }, 500);
  }
  return <Child val={val} getData={getData} />;}function Child({val, getData}) {
  useEffect(() => {
    getData();
  }, [getData]);
  return <div>{val}</div>;}

就這么輕輕松松,一個死循環就誕生了…

先來分析下這段代碼的用意,Child組件是一個純展示型組件,其業務邏輯都是通過外部傳進來的,這種場景在實際開發中很常見。

再分析下代碼的執行過程:

  • App渲染Child,將val和getData傳進去
  • Child使用useEffect獲取數據。因為對getData有依賴,于是將其加入依賴列表
  • getData執行時,調用setVal,導致App重新渲染
  • App重新渲染時生成新的getData方法,傳給Child
  • Child發現getData的引用變了,又會執行getData
  • 3 -> 5 是一個死循環

如果明確getData只會執行一次,最簡單的方式當然是將其從依賴列表中刪除。但如果裝了 hook 的lint 插件,會提示:React Hook useEffect has a missing dependency

useEffect(() => {
  getData();}, []);

實際情況很可能是當getData改變的時候,是需要重新獲取數據的。這時就需要通過useCallback來將引用固定?。?/p>

const getData = useCallback(() => {
  setTimeout(() => {
    setVal("new data " + count);
    count++;
  }, 500);}, []);

上面例子中getData的引用永遠不會變,因為他它的依賴列表是空??梢愿鶕嶋H情況將依賴加進去,就能確保依賴不變的情況下,函數的引用保持不變。

還有一個要注意的是

在開始監聽一個鼠標的移動的時候,想要刪除這個監聽不生效,由于是, 加入useState導致組件再次渲染 handleMouse 函數在次渲染, handleMouse 作為組件內的方法, 會跟著一同再次渲染, 并且在內存里, 再次渲染出的 clickFunc !== 前clickFunc.

所以removeEventListener無法解除綁定, 再次addEventListener則會綁定一個新方法.

document.addEventListener('mousemove',handleMouse,true)

解決方案 : useCallback 緩存改方法 這時候的 document.removeEventListener(‘mousemove’,handleMouse,true) 中的handleMouse 和添加中的方法就是一個了,就能刪除了。

onst handleMouse= useCallback(() => {
//xxxx
    console.log("clicking");
  }, []);

原文鏈接:https://blog.csdn.net/weixin_42910765/article/details/128344167

欄目分類
最近更新