簡體   English   中英

React鈎子useCallback與循環內的參數

[英]React hooks useCallback with parameters inside loop

我正在嘗試了解鈎子功能,但我似乎無法弄清楚我應該如何正確使用函數useCallback 據我所知,關於鈎子的規則我應該稱它們為頂級而不是邏輯(如循環)。 這讓我很困惑,我應該如何在從循環中呈現的組件上實現useCallback

看一下下面的示例代碼片段,其中我創建了5個帶有onClick處理程序的按鈕,該處理程序將按鈕的編號打印到控制台。

 const Example = (props) => { const onClick = (key) => { console.log("You clicked: ", key); }; return( <div> { _.times(5, (key) => { return ( <button onClick={() => onClick(key)}> {key} </button> ); }) } </div> ); }; console.log("hello there"); ReactDOM.render(<Example/>, document.getElementById('root')); 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id='root'> </div> 

由於我在<button onClick={() => onClick(key)}>使用了箭頭函數,因此每次示例呈現時它都會創建一個新的函數實例,我這樣做是因為我希望onClick函數知道哪個按鈕叫它。 我認為我可以通過使用useCallback來阻止這個新的反應鈎子功能,但是如果我將它應用於const onClick那么它仍會在每次渲染時創建一個新實例,因為提供key參數所需的內聯箭頭功能,我據我所知,不允許將它應用於循環中的渲染(特別是如果循環順序可能會改變嗎?)。

那么在保持相同功能的同時,如何在這種情況下實現useCallback呢? 它可能嗎?

這里簡單的答案是,你可能不應該在這里使用useCallback useCallback是將相同的函數實例傳遞給優化的組件(例如PureComponentReact.memo組件)以避免不必要的重新渲染。

在這種情況下你沒有處理優化的組件(或者大多數情況下,我懷疑)因此沒有理由useCallbackuseCallback這樣的回調。


假設記憶很重要,這里最好的解決方案可能是使用單個函數而不是五個:而不是每個按鈕的唯一函數通過閉包來攜帶key ,您可以將key附加到元素:

<button data-key={key}>{key}</button>

然后在單擊處理程序中讀取event.target.dataset["key"]

 const Example = (props) => { // Single callback, shared by all buttons const onClick = React.useCallback((e) => { // Check which button was clicked const key = e.target.dataset["key"] console.log("You clicked: ", key); }, [/* dependencies */]); return( <div> { _.times(5, (key) => { return ( <button data-key={key} onClick={onClick}> {key} </button> ); }) } </div> ); }; console.log("hello there"); ReactDOM.render(<Example/>, document.getElementById('root')); 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id='root'> </div> 


總而言之,可以在一個鈎子中記憶多個功能。 useCallback(fn, deps)等同於useMemo(() => fn, deps)useMemo可用於一次useMemo多個函數:

const clickHandlers = useMemo(() => _.times(5, key => 
  () => console.log("You clicked", key)
), [/* dependencies */]);

 const Example = (props) => { const clickHandlers = React.useMemo(() => _.times(5, key => () => console.log("You clicked", key) ), [/* dependencies */]) return( <div> { _.times(5, (key) => { return ( <button onClick={clickHandlers[key]}> {key} </button> ); }) } </div> ); }; console.log("hello there"); ReactDOM.render(<Example/>, document.getElementById('root')); 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script> <div id='root'> </div> 

也許有一種情況,這是有用的,但在這種情況下,我要么不管它(而不是擔心優化)或者為每個按鈕使用一個處理程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM