首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >未捕获的不变冲突:比上一次渲染时渲染更多的钩子

未捕获的不变冲突:比上一次渲染时渲染更多的钩子
EN

Stack Overflow用户
提问于 2019-04-11 07:45:04
回答 4查看 105.9K关注 0票数 66

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

代码语言:javascript
复制
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.我试图找到这个错误的解释,但是我的搜索没有返回任何结果。

当我稍微修改组件时:

代码语言:javascript
复制
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函数吗?如果能解释一下为什么这个修复是有效的,那就太好了。

EN

回答 4

Stack Overflow用户

发布于 2021-01-04 13:51:03

我也面临着同样的问题。我正在做的事情是这样的:

代码语言:javascript
复制
const Table = (listings) => {

    const {isLoading} = useSelector(state => state.tableReducer);

    if(isLoading){
        return <h1>Loading...</h1>
    }

    useEffect(() => {
       console.log("Run something")
    }, [])

    return (<table>{listings}</table>)
}

我认为发生的情况是在第一次渲染时,组件提前返回,useEffect没有运行。当isLoading状态改变时,useEffect运行,我得到了错误-钩子渲染的次数比上次渲染的次数更多。

一个简单的改变就可以解决这个问题:

代码语言:javascript
复制
const Table = (listings) => {
    
    const {isLoading} = useSelector(state => state.tableReducer);
        
    useEffect(() => {
        console.log("Run something")
    }, [])
    
    if(isLoading){
        return <h1>Loading...</h1>
    }
    return (<table>{listings}</table>)
}
票数 25
EN

Stack Overflow用户

发布于 2019-04-11 16:31:40

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

代码语言:javascript
复制
<p onClick={() => setAllResultsVisible(!allResultsVisible) }> 
    More results v
</p>

它将完美地工作

票数 20
EN

Stack Overflow用户

发布于 2020-08-17 17:55:27

即使在上面的修复之后,也有一些其他原因导致了这个错误。我在下面写下我遇到的一个用例。

代码语言:javascript
复制
function Comp(props){return <div>{props.val}</div>}

在jsx中可以通过以下方式调用此组件:

代码语言:javascript
复制
1. <Comp val={3} /> // works well
2. { Comp({val:3}) } // throws uncaught invariant violation error, at least it throw in my case, may be there were other factors, but changing back to first way removed that problem
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55622768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档