使用 React Hooks 获得“太多重新渲染”错误
Posted
技术标签:
【中文标题】使用 React Hooks 获得“太多重新渲染”错误【英文标题】:Getting a "Too many re-renders" error with 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 钩子应该用于执行副作用,虽然我不知道在这种情况下如何使用它(假设它是必要的)。
【问题讨论】:
【参考方案1】:触发错误是因为您在渲染函数中直接使用setText
。该函数在调用后渲染组件。因为在下一次渲染中,data
和 error
仍然设置,所以它再次调用了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
回调,不错!
天哪,我为什么没有考虑这个解决方案?非常感谢!!以上是关于使用 React Hooks 获得“太多重新渲染”错误的主要内容,如果未能解决你的问题,请参考以下文章
useEffect 中的 state 总是使用 React Hooks 引用初始状态