javascript Uncaught Invariant Violation:渲染的钩子比上一次渲染时更多

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/55622768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:33:48  来源:igfitidea点击:

Uncaught Invariant Violation: Rendered more hooks than during the previous render

javascriptreactjsreact-hooks

提问by timothym

I have a component that looks like this (very simplified version):

我有一个看起来像这样的组件(非常简化的版本):

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>;
}

When I load the page this component is used on, I get this error: Uncaught Invariant Violation: Rendered more hooks than during the previous render.I tried to find an explanation of this error, but my searching returned no results.

当我加载使用此组件的页面时,出现此错误:Uncaught Invariant Violation: Rendered more hooks than during the previous render.我试图找到此错误的解释,但我的搜索未返回任何结果。

When I modify the component slightly:

当我稍微修改组件时:

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>;
}

I no longer get that error. Is it because I included the setStatefunction within the jsx that is returned by renderResults? It would be great to have an explanation of why the fix works.

我不再得到那个错误。是不是因为我setState在 jsx 中包含了由 返回的函数renderResults?最好能解释一下此修复程序的工作原理。

采纳答案by Jake Worth

The fix works because the first code sample (the erroring one) invokes a function inside onClick, while the second (the working one) passes a function to onClick. The difference is those all-important parentheses, which in JavaScript mean 'invoke this code'.

该修复程序有效,因为第一个代码示例(出错的那个)调用了 内部的一个函数onClick,而第二个(工作中的)将一个函数传递给了onClick。区别在于那些非常重要的括号,它们在 JavaScript 中的意思是“调用此代码”。

Think of it this way: in the first code sample, every time componentis rendered, renderResultsis invoked. Every time that happens, setAllResultsVisible(!allResultsVisible), rather than waiting for a click, is called. Since React performs the render on its own schedule, there's no telling how many times that will happen.

可以这样想:在第一个代码示例中,每次component渲染、renderResults调用。每次发生这种情况时setAllResultsVisible(!allResultsVisible),都会调用 ,而不是等待点击。由于 React 按照自己的时间表执行渲染,因此不知道会发生多少次。

From the React docs:

来自 React 文档:

With JSX you pass a function as the event handler, rather than a string.

使用 JSX,您可以传递一个函数作为事件处理程序,而不是一个字符串。

React Handling Events Docs

React 处理事件文档

Note: I wasn't able to get this exact error message when running the first code sample in a sandbox. My error referred to an infinite loop. Maybe a more recent version of React produces the error described?

注意:在沙箱中运行第一个代码示例时,我无法获得此确切的错误消息。我的错误是指无限循环。也许更新版本的 React 会产生所描述的错误?

回答by Ertan Hasani

You can simply change your onlick event add () =>before setAllResultsVisible

您可以在 setAllResultsVisible() =>之前简单地更改您的 onlick 事件添加

<p onClick={() => setAllResultsVisible(!allResultsVisible) }> 
    More results v
</p>

and it will work perfectly

它会完美地工作