React 同步獲取 useState 的最新值


一、問題案例

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
	setCount(2);
	fn(); // 點擊后打印 0
  };

  const fn = () => {
	console.log(count);
  };

  return (
	<div className="App">
	  <button onClick={handleClick}>點擊</button>
	</div>
  );
}

二、原因分析

1.為什么在 fn 中打印出來的 count 是 0 呢?
因為 React 合成事件中,為了減少 render 次數,提高性能,React 會將多次狀態更新收集起來,最后一次更新,所以在 React 合成事件中,狀態更新是異步的,fn 和 setCount 在同一個宏任務中,這時候 React 還沒有 render,所以獲取到的 count 還是上一次閉包里的值 0。

三、解決思路

1.通過傳參的形式,將最新的值,傳遞給 fn
2.render 之后,在 useEffect 中獲取
3.自定義一個 hook useSyncCallback

四、useSyncCallback 代碼實現

import { useEffect, useState, useCallback } from 'react'

const useSyncCallback = callback => {
	const [proxyState, setProxyState] = useState({ current: false })
	const [params, setParams] = useState([])

	const Func = useCallback((...args) => {
		setParams(args)
		setProxyState({ current: true })
	}, [proxyState])

	useEffect(() => {
		if (proxyState.current === true) setProxyState({ current: false })
	}, [proxyState])

	useEffect(() => {
		proxyState.current && callback(...params)
	})

	return Func
}

export default useSyncCallback

使用 useSyncCallback

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
	setstate(2);
	fn(); // 打印 2
  };
  /** 將fn的方法傳遞給 useSyncCallback 然后返回一個新的函數 */
  const fn = useSyncCallback(() => {
	console.log(count);
  });

  return (
	<div className="App">
	   <button onClick={handleClick}>點擊</button>
	</div>
  );
}

export default App;

參考文獻


免責聲明!

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



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