簡體   English   中英

React 鈎子值正確呈現但未在 addEventListener 的回調 function 中更新

[英]React hooks value renders correctly but not updated inside a callback function of addEventListener

我在功能組件中使用鈎子實現無限滾動,我遇到了一個問題,我無法訪問滾動事件回調 function 中的更新值,這是我的代碼:

 // Get a hook function const {useState, useEffect} = React; const initItems = ['First', 'Second','Third','Fourth','Fifth'] const Example = ({title}) => { const [posts, setPosts] = useState({ data: [], page: 1 }); console.log('FN RENDER') const handleScroll = (e) => { const { scrollHeight, scrollTop, clientHeight } = e.target const bottom = scrollHeight - scrollTop === clientHeight; if (bottom) { console.log('page', posts.page) // page stays 1 const nextPage = posts.page + 1 setPosts(p => ({ data: [...p.data, 'Append'], page: p.page + 1 })) } } useEffect(() => { console.log('USEEFFECT RENDER') setPosts(p => ({ data: initItems, page: 1 })) //using ScrollBox for demo, originally I'm handling the scroll event on the document: document.addEventListener document.getElementById("ScrollBox").addEventListener('scroll',handleScroll); return () => document.getElementById("ScrollBox").removeEventListener('scroll', handleScroll); }, []); return ( <div> <p>Page:{posts.page}</p> <div id="ScrollBox" class="scroll-box"> { posts.data.map(k=> <p>{k} </p>) } </div> </div> ); }; // Render it ReactDOM.render( <Example />, document.getElementById("react") );
 #ScrollBox{ border:1px solid red; height:100px; overflow:auto; width:400px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>

如果您查看控制台, page的值在正確呈現時保持為1 我使用useEffect來附加事件。 如何在handleScroll中獲得正確的更新值?

- 編輯 -

如何在addEventListener的回調中獲取更新的值? #ScrollBox用於問題演示,我需要檢測document上的滾動,這就是我使用事件偵聽器的原因。

useEffect function 僅在第二個參數發生更改時觸發。 由於您有一個空的第二個參數,因此它永遠不會更新,並且由於它永遠不會更新,因此無論您更新 state 多少次,您的事件處理程序都會從第一次渲染開始保持陳舊的關閉。

您可以通過在渲染 function 而不是在useEffect中直接傳遞事件偵聽器來修復您的代碼。 無論如何,您都不應該在 react 中進行直接的 DOM 操作。

 // Get a hook function const {useState, useEffect} = React; const initItems = ['First', 'Second','Third','Fourth','Fifth'] const Example = ({title}) => { const [posts, setPosts] = useState({ data: [], page: 1 }); console.log('FN RENDER') const handleScroll = (e) => { const { scrollHeight, scrollTop, clientHeight } = e.target const bottom = scrollHeight - scrollTop === clientHeight; if (bottom) { console.log('page', posts.page) // page stays 1 const nextPage = posts.page + 1 setPosts(p => ({ data: [...p.data, 'Append'], page: p.page + 1 })) } } useEffect(() => { console.log('USEEFFECT RENDER') // <:-- No event handler here --> setPosts(p => ({ data, initItems: page, 1 })) }; []): return ( <div> <p>Page.{posts.page}</p> <.-- NOTE THE EVENT HANDLER HERE --> <div id="ScrollBox" class="scroll-box" onScroll={handleScroll} > { posts;data;map(k=> <p>{k} </p>) } </div> </div> ). }, // Render it ReactDOM.render( <Example />; document.getElementById("react") );
 #ScrollBox{ border:1px solid red; height:100px; overflow:auto; width:400px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>

暫無
暫無

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

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