You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks触发‘Too many re-renders’错误的代码重构方案咨询

Fixing the "Too many re-renders" Error in Your React Query Email Verification Component

Hey David, let's break down what's causing that frustrating loop and fix it with useEffect—exactly what you suspected you needed!

The Root of the Problem

Right now, you're calling setText() directly in the component's render body. Every time your component renders (which happens after any state update), it checks if error or data exists and updates the text state. That state update triggers another render, which checks error/data again, updates state again, and so on—creating an infinite loop of re-renders.

The Fix: Use useEffect for Side Effects

useEffect lets you run code after render, and only when specific dependencies change. We'll use it to update text only when data or error from useQuery changes, breaking the loop.

Here's the refactored code:

const EmailVerification = () => { 
  const [showMessage, setShowMessage] = useState(true); 
  const [text, setText] = useState("...Loading. Do not close."); 
  const { data, error } = useQuery(VERIFY_EMAIL); 

  useEffect(() => {
    // Update text only when data or error changes
    if (error) {
      setText(genericErrorMessage);
    } else if (data) {
      setText(emailVerificationMessage);
    }
    // Dependencies array: run this effect only when these values change
  }, [data, error, genericErrorMessage, emailVerificationMessage]);

  return ( 
    <Wrapper> 
      <Message setShowMessage={setShowMessage} text={text} /> 
    </Wrapper> 
  ) 
}

Why This Works

  • The useEffect callback runs after the component renders, not during render.
  • The dependencies array ([data, error, ...]) tells React to only re-run this effect when those values change. So when useQuery finishes fetching and updates data or error, the effect runs once to update text—no infinite loops.
  • We added genericErrorMessage and emailVerificationMessage to the dependencies to avoid stale closures (if these values ever change, the effect will pick up the latest version).

Bonus: Simplify with Conditional Rendering (Optional)

If you don't need text as a separate state (since it's derived from data/error), you could even skip the state entirely and compute the text directly in the render:

const EmailVerification = () => { 
  const [showMessage, setShowMessage] = useState(true); 
  const { data, error } = useQuery(VERIFY_EMAIL); 

  const text = error 
    ? genericErrorMessage 
    : data 
      ? emailVerificationMessage 
      : "...Loading. Do not close.";

  return ( 
    <Wrapper> 
      <Message setShowMessage={setShowMessage} text={text} /> 
    </Wrapper> 
  ) 
}

This avoids state updates entirely, which is even cleaner if your text doesn't need to be stateful. Either approach will fix the re-render loop!

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 15:12:34