簡體   English   中英

如何在 React 的 useEffect 中將 State 更新傳遞給自定義渲染循環?

[英]How To Pass State Update To Custom Render Loop In React's `useEffect`?

我經常遇到這樣的情況,我構建了一個基於window.requestAnimationFrame的渲染循環,但是想要在循環內部交換一些狀態。 有幾種方法可以做到這一點,但我不確定哪種方法最好。 我的設置通常是這樣的:

function Animation({someState}) {
  const loopDataRef = useRef();
  useEffect(() => {
    //do something initialization work for the renderloop, e.g. getContext, etc.
    let frame;
    const loop = (cts) => {
      frame = window.requestAnimationFrame(loop)
      //do some loop work using someState and loopDataRef.current
    }
    loop();
    return () => window.cancelAnimationFrame(frame);
  }, []);
}

請注意,在循環中使用someState將始終使用效果的最后一次運行的值,不一定是當前值。 以下是一些顯而易見的解決方案:

  • 我可以將someState放在 useEffect 的依賴數組中,這樣只要useEffect發生變化,循環就會重新啟動。 但是如果初始化很昂貴,例如使用 WebGL,我在那里創建所有紋理並編譯着色器,它似乎不是很優雅。

  • 我可以使用兩種效果,一種用於循環本身的初始化,另一種僅用於循環,它在每次 state 更改時停止和啟動。 但我仍然認為,理想情況下,animation 循環應該一直運行到停止,而不是在其間停止/啟動。

  • 另一個具有兩種效果的解決方案,但這次我執行const someStateRef = useRef()然后在其依賴數組中使用someState創建一個效果,它只是將someState寫入someStateRef.current因此我可以在循環中使用它。 是我實現它的示例。 或者,可以在每次渲染時將someState寫入someStateRef.current ,而不會產生其他影響。 看起來非常高效,但不是很優雅。

最 React 的方式是什么?

我將 go 與您已經實施的第三個選項,因為它看起來與 React Hooks FAQ(第三個代碼塊)中的一個示例完全一樣:

function Example(props) {
  // Keep latest props in a ref.
  const latestProps = useRef(props);
  useEffect(() => {
    latestProps.current = props;
  });

  useEffect(() => {
    function tick() {
      // Read latest props at any time
      console.log(latestProps.current);
    }

    const id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, []); // This effect never re-runs
}

(將set/clearInterval替換為request/cancelAnimationFrame

為了完整起見:前兩個選項存在您提到的缺陷,不建議在每次渲染時將someStateRef.current寫入someState而沒有其他效果。

避免在渲染期間讀取和更新引用,因為這會使組件的行為難以預測和理解。

來源

暫無
暫無

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

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