如何用useEffect
模擬componentDidMount
生命週期?
雖然可以使用 useEffect(fn, [])
,但它們並不完全相等。和 componentDidMount
不一樣,useEffect
會捕獲 props
和state
。所以即便在回調函數裏,你拿到的還是初始的 props
和 state
。如果你想得到“最新”的值,你可以使用 ref
。不過,通常會有更簡單的實現方式,所以你並不一定要用 ref
。
如何正確地在useEffect
裏請求數據?[]
又是什麼?
下片篇文章介紹瞭如何在useEffect裏做數據請求。[]
表示 effect
沒有使用任何React數據流裏的值,因此該 effect
僅被調用一次是安全的。[]
同樣也是一類常見問題的來源,即使你以爲沒使用數據流裏的值,但其實使用了。你需要學習一些策略(主要是useReducer
和 useCallback
)來移除這些 effect
依賴。
我應該把函數當做effect
的依賴嗎?
一般建議把不依賴 props
和 state
的函數提到你的組件外面,並且把那些僅被 effect
使用的函數放到 effect
裏面。如果這樣做了以後,你的 effect
還是需要用到組件內的函數(包括通過props
傳進來的函數),可以在定義它們的地方用useCallback
包一層。爲什麼要這樣做呢?因爲這些函數可以訪問到props
和state
,因此它們會參與到數據流中。
爲什麼有時候會出現無限重複請求的問題?
這個通常發生於你在 effect
裏做數據請求並且沒有設置 effect
依賴參數的情況。沒有設置依賴,effect
會在每次渲染後執行一次,然後在 effect
中更新了狀態引起渲染並再次觸發 effect
。無限循環的發生也可能是因爲你設置的依賴總是會改變。你可以通過一個一個移除的方式排查出哪個依賴導致了問題。但是,移除你使用的依賴(或者盲目地使用[]
)通常是一種錯誤的解決方式。你應該做的是解決問題的根源。舉個例子,函數可能會導致這個問題,你可以把它們放到effect
裏,或者提到組件外面,或者用 useCallback
包一層。useMemo
可以做類似的事情以避免重複生成對象。
爲什麼有時候在effect
裏拿到的是舊的state
或prop
呢?
Effect拿到的總是定義它的那次渲染中的props
和state
。這能夠避免一些bugs,但在一些場景中又會有些討人嫌。對於這些場景,你可以明確地使用可變的ref
保存一些值。如果你覺得在渲染中拿到了一些舊的props
和state
,且不是你想要的,你很可能遺漏了一些依賴。