使用 React Hooks 的時候,常常出現執行次數過多甚至死循環的狀況,咱們能夠利用 use-what-changed 進行依賴分析,找到哪一個變量引用一直在變化。前端
據一個例子,好比你嘗試在 Class 組件內部渲染 Function 組件,Class 組件是這麼寫的:git
class Parent extends React.PureComponent { render() { return <Child style={{ color: "red" }} />; } }
子組件是這麼寫的:github
const Child = ({ style }) => { const [localStyle, setLocalStyle] = useState(); useEffect(() => { setLocalStyle(style); }, [style]); return null; };
那麼恭喜你,寫出了一個最簡單的死循環。這個場景裏,咱們本意是利用 useEffect
將 props.style
同步到本地狀態 localStyle
中,但執行 setLocalStyle
會致使當前組件重渲染,因爲父級 style={{ color: "red" }}
的寫法,每次重渲染拿到的 props.style
引用都會變化,所以再次觸發了 useEffect
回調執行,進而再次執行到 setLocalStyle
觸發死循環。數組
僅僅打印出值是看不出變化的,引用的改變很隱蔽,爲了判斷是否變化還得存儲上一次的值作比較,很是麻煩,use-what-changed 就是爲了解決這個麻煩的。微信
use-what-changed 使用方式以下:babel
function App() { useWhatChanged([a, b, c, d]); // debugs the below useEffect React.useEffect(() => { // console.log("some thing changed , need to figure out") }, [a, b, c, d]); }
將參數像依賴數組同樣傳入,刷新頁面就能夠在控制檯看到引用或值是否變化,若是變化,對應行會展現 ✅ 並打印出上次的值與當前值:工具
第一步是存儲上一次依賴項的值,利用 useRef
實現:性能
function useWhatChanged(dependency?: any[]) { const dependencyRef = React.useRef(dependency); }
而後利用 useEffect
,對比 dependency
與 dependencyRef
的引用便可找到變化項:spa
React.useEffect(() => { let changed = false; const whatChanged = dependency ? dependency.reduce((acc, dep, index) => { if (dependencyRef.current && dep !== dependencyRef.current[index]) { changed = true; const oldValue = dependencyRef.current[index]; dependencyRef.current[index] = dep; acc[`"✅" ${index}`] = { "Old Value": getPrintableInfo(oldValue), "New Value": getPrintableInfo(dep), }; return acc; } acc[`"⏺" ${index}`] = { "Old Value": getPrintableInfo(dep), "New Value": getPrintableInfo(dep), }; return acc; }, {}) : {}; if (isDevelopment) { console.table(whatChanged); } }, [dependency]);
changed
設爲 true。以上就是其源碼的核心邏輯,固然咱們還能夠簡化輸出,僅當有引用變化時纔打印表格,不然只輸出簡單的 Log 信息:插件
if (isDevelopment) { if (changed) { console.table(whatChanged); } else { console.log(whatChanged); } }
最後 use-what-changed 還提供了 babel 插件,只經過註釋就能打印 useMemo
、useEffect
等依賴變化信息。babel 配置以下:
{ "plugins": [ [ "@simbathesailor/babel-plugin-use-what-changed", { "active": process.env.NODE_ENV === "development" // boolean } ] ] }
使用方式簡化爲:
// uwc-debug React.useEffect(() => { // console.log("some thing changed , need to figure out") }, [a, b, c, d]);
將 Hooks 的 deps 數組直接轉化爲 use-what-changed 的入參。
use-what-changed 補充了 Hooks 依賴變化的調試方法,對於 React 組件重渲染分析能夠利用 React Dev Tool,能夠參考 精讀《React 性能調試》。
還有哪些實用的 Hooks 調試工具呢?歡迎分享。
討論地址是: 精讀《use-what-changed 源碼》· Issue #256 · dt-fe/weekly
若是你想參與討論,請 點擊這裏,每週都有新的主題,週末或週一發佈。前端精讀 - 幫你篩選靠譜的內容。
關注 前端精讀微信公衆號
版權聲明:自由轉載-非商用-非衍生-保持署名( 創意共享 3.0 許可證)
本文使用 mdnice 排版