簡體   English   中英

React 鈎子會導致無意的重新渲染

[英]React hooks cause unintentional re-render

我正在使用 React + Leaflet map 並注意到 map 容器/元素在我顯示或關閉模式時重新渲染。

我創建了一個沙箱來演示該問題,但如果其他示例有幫助,這會在我的應用程序中的其他地方發生。

https://codesandbox.io/s/elegant-rain-01f9l?file=/src/App.js

通過閱讀替代 SO 帖子,例如這個非常相似的帖子,我認識到這可能是由我的鈎子(例如 handleShow/setShow)引起的,它強制整個組件重新渲染。 意外行為如下所示:

如果拖動 map 使當前位置不在視野范圍內並打開模態框,我們會強制重新加載<LeafletControlGeocoder/><LocationMarker/> 這很明顯,因為 map 會重新平移到當前位置,並且 map 的右上角會出現一個新的“搜索圖標”。

復制步驟:

*如果您在沙箱中發現與 react-bootstrap/Modal 相關的問題,只需將依賴項更新為最新(刷新圖標) - 這是一個奇怪的沙箱問題,但與我的問題無關。

  1. 拖動 map 使當前位置不在視野范圍內
  2. 單擊菜單圖標(右上角)> 添加位置
  3. 當模態出現時,請注意 map 重新居中到當前位置並出現另一個搜索圖標。

該問題是由於在另一個 React 功能組件的主體中定義了一些子組件 function 引起的。

function App() { // A React functional component
  const [show, setShow] = useState(false);
  // etc.

  // A child React functional component in the body of another component...
  function LocationMarker() {
    const [position, setPosition] = useState(null);
    // etc.
  }

  // Another child component
  function LeafletControlGeocoder() {
    useEffect(() => {}, []);
    // etc.
  }

  return (
    <>
      {/* More content... */}
      <MapContainer center={[45.4, -75.7]} zoom={12}>
        <LeafletControlGeocoder />
        <LocationMarker />
      </MapContainer>
    </>
  );
}

如果您的子組件是無狀態的(沒有掛鈎),這可能不會有問題。 在這種情況下,它們更像是“子模板”。

但是如果這些子組件確實使用了一些鈎子,那么在另一個功能組件的主體中會干擾鈎子的工作方式:因為子組件 function 在每次重新渲染時都會重新創建,React 無法識別這些子組件是相同的組件,最終復制了他們的 output。

只需確保不要在另一個中定義一些功能組件,而是始終在 scope 的頂層(通常在文件的根目錄)。 如問題評論中所述,標准做法是每個文件只有一個組件。

function App() { // A React functional component
  const [show, setShow] = useState(false);
  // etc.

  return (
    <>
      {/* More content... */}
      <MapContainer center={[45.4, -75.7]} zoom={12}>
        <LeafletControlGeocoder />
        <LocationMarker />
      </MapContainer>
    </>
  );
}

// Another React functional component at top scope level
function LocationMarker() {
  const [position, setPosition] = useState(null);
  // etc.
}

// Another component
function LeafletControlGeocoder() {
  useEffect(() => {}, []);
  // etc.
}

固定應用程序: https://codesandbox.io/s/lively-monad-yve67

暫無
暫無

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

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