我有一个看起来像这样的组件(非常简化的版本):
const component = (props: PropTypes) => { const [allResultsVisible, setAllResultsVisible] = useState(false); const renderResults = () => { return ( <section> <p onClick={ setAllResultsVisible(!allResultsVisible) }> More results v </p> { allResultsVisible && <section className="entity-block--hidden-results"> ... </section> } </section> ); }; return <div>{ renderResults() }</div>; }
当我加载使用此组件的页面时,出现此错误:Uncaught Invariant Violation: Rendered more hooks than during the previous render.
我试图找到此错误的解释,但是我的搜索没有返回结果。
当我稍微修改组件时:
const component = (props: PropTypes) => { const [allResultsVisible, setAllResultsVisible] = useState(false); const handleToggle = () => { setAllResultsVisible(!allResultsVisible); } const renderResults = () => { return ( <section> <p onClick={ handleToggle }> More results v </p> { allResultsVisible && <section className="entity-block--hidden-results"> ... </section> } </section> ); }; return <div>{ renderResults() }</div>; }
我不再收到该错误。是因为我在 renderResults
返回的 jsx 中包含了 setState
函数吗?如果能够解释该修复为何有效,那就太好了。
我也遇到了同样的问题。我正在做的事情是这样的:
我认为发生的情况是在第一次渲染时,组件提前返回并且 useEffect 没有运行。当 isLoading 状态更改时,useEffect 运行,我收到错误 - 钩子渲染的次数比之前的渲染次数多。
一个简单的更改就解决了这个问题:
该修复之所以有效,是因为第一个代码示例(出错的代码)调用了
onClick
内的函数,而第二个代码示例(有效的代码示例)则将函数传递给了onClick
。区别在于那些非常重要的括号,在 JavaScript 中意味着“调用此代码”。这样想:在第一个代码示例中,每次渲染
component
时,都会调用renderResults
。每次发生这种情况时,都会调用setAllResultsVisible(!allResultsVisible)
,而不是等待单击。由于 React 按照自己的时间表执行渲染,因此无法确定会发生多少次。来自 React 文档:
React 处理事件文档
注意:在沙箱中运行第一个代码示例时,我无法获得确切的错误消息。我的错误涉及无限循环。也许较新版本的 React 会产生所描述的错误?