【问题标题】:Getting a "Too many re-renders" error with React Hooks使用 React Hooks 获得“太多重新渲染”错误
【发布时间】:2021-11-21 08:57:22
【问题描述】:

我在这里为 React Hooks 苦苦挣扎。我在网上查看,但无法弄清楚如何将示例调整到我的代码中。我有以下组件会触发“重新渲染过多”错误:

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

  const { data, error } = useQuery(VERIFY_EMAIL);
  if (error) {setText(genericErrorMessage);}
  if (data) {setText(emailVerificationMessage);}

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

如何重新组织我的代码以避免此错误?我知道 useEffect 钩子应该用于执行副作用,虽然我不知道在这种情况下如何使用它(假设它是必要的)。

【问题讨论】:

    标签: reactjs react-hooks graphql apollo-client use-state


    【解决方案1】:

    触发错误是因为您在渲染函数中直接使用setText。该函数在调用后渲染组件。因为在下一次渲染中,dataerror 仍然设置,所以它再次调用了setText

    关于useEffect,你是对的。使用useEffect,您可以确保仅在数据发生更改时才调用setText 函数。在您的情况下,这适用于 data 和/或 error 变量。

    import { useEffect } from 'react';
    
    const EmailVerification = () => {
      const [showMessage, setShowMessage] = useState(true);
      const [text, setText] = useState("...Loading. Do not close.");
    
      const { data, error } = useQuery(VERIFY_EMAIL);
      
      useEffect(() => {
        if (error) setText('message');
        if (data) setText('emailVerificationMessage');
      }, [error, data]);
      
      return (
        <Wrapper>
          <Message setShowMessage={setShowMessage} text={text} />
        </Wrapper>
      )
    }
    

    但是,由于您只是使用现有的道具更改 text 变量,因此您也可以仅在 JS(X) 中执行此操作:

    
    const EmailVerification = () => {
      const [showMessage, setShowMessage] = useState(true);
      const { isLoading, data, error } = useQuery(VERIFY_EMAIL);
      
      const text = isLoading ? 'Loading... Do not close' : error || !data ? 'Error message' : 'emailVerificationMessage';
    
      return (
        <Wrapper>
          <Message setShowMessage={setShowMessage} text={text} />
        </Wrapper>
      )
    }
    

    这使用嵌套的三元运算符(不是风扇),可以用任何其他方法替换。

    【讨论】:

    • 优秀的答案。谢谢你,克里斯。
    【解决方案2】:

    setText 将导致重新渲染,并将在下一次渲染时再次调用。据我了解,您希望在查询返回错误或数据后设置文本。

    为避免这种情况,请使用 onError 和 onCompleted ,您可以像这样传递给 useQuery :

    const { data, error } = useQuery(VERIFY_EMAIL, {
      onCompleted: () => setText(emailVerificationMessage),
      onError: () => setText(genericErrorMessage)
    });
    

    并删除这两行:

    if (error) {setText(genericErrorMessage);}
    if (data) {setText(emailVerificationMessage);}
    

    或在 useEffect 中调用 setText:

    useEffect(() => {
      if (error) {
        setText(genericErrorMessage)
      }
    }, [error])
    

    【讨论】:

    • useQuery 回调,不错!
    • 天哪,我为什么没有考虑这个解决方案?非常感谢!!
    猜你喜欢
    • 1970-01-01
    • 2021-03-22
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2020-02-23
    • 1970-01-01
    相关资源
    最近更新 更多