programing

적발되지 않은 불변 위반:이전 렌더링 때보다 더 많은 후크가 렌더링되었습니다.

powerit 2023. 3. 29. 21:58
반응형

적발되지 않은 불변 위반:이전 렌더링 때보다 더 많은 후크가 렌더링되었습니다.

다음과 같은 컴포넌트가 있습니다(매우 간단한 버전).

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

그 에러는 더 이상 발생하지 않습니다.가 그유 the the the the the the the the the the is를 인가?setStaterenderResults수정이 왜 기능하는지 설명해 주시면 감사하겠습니다.

저도 같은 문제에 직면했어요.제가 하고 있는 일은 다음과 같습니다.

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가 실행되어 이전 렌더보다 여러 번 훅이 렌더링된 오류가 발생하였습니다.

간단한 변경으로 해결:

const Table = (listings) => {
    
    const {isLoading} = useSelector(state => state.tableReducer);
        
    useEffect(() => {
        console.log("Run something")
    }, [])
    
    if(isLoading){
        return <h1>Loading...</h1>
    }
    return (<table>{listings}</table>)
}

은 첫 샘플이 내부 합니다.onClick (하고 있는 것)는를 [실행하고 있는 것]으로 onClick차이점은 모두 중요한 괄호입니다.JavaScript를 사용합니다.

번째 코드샘플에서는 """ "" "" " " " " " " " " " " " " " " " " " " " " " " " " " 입니다.첫 번째 코드 샘플에서는 매번componentrenderResults마다, 그럴때 마다, 그럴 때 마다.setAllResultsVisible(!allResultsVisible)를 호출합니다.React는 자체 스케줄에 따라 렌더링을 수행하므로 몇 번이나 렌더링이 수행될지는 알 수 없습니다.

React 문서에서:

JSX에서는 문자열이 아닌 이벤트핸들러로서 함수를 전달합니다.

리액트 핸들링 이벤트 문서

주의: 샌드박스에서 첫 번째 코드샘플을 실행했을 때 이 오류 메시지가 정확히 표시되지 않았습니다.내 오류는 무한 루프입니다.React의 최신 버전을 사용하면 설명된 오류가 발생할 수 있습니다.

추가는 간단하게 할 수 .() => AllResultsVisiblesetAllResultsVisible 전 »

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

그리고 완벽하게 작동될 것이다.

위의 수정 후에도 이 오류에는 몇 가지 다른 원인이 있습니다.아래에 저에게 발생한 사용 사례를 하나 적어드립니다.

function Comp(props){return <div>{props.val}</div>}

이 컴포넌트는 jsx에서 다음 방법으로 호출할 수 있습니다.

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

질문은 '리액트'로 할 수 있습니다.

  1. 이전 렌더링보다 적은 후크를 렌더링했습니다.
  2. 이전 렌더링보다 더 많은 후크를 렌더링했습니다.

두 경우 모두 부모 반환 함수에 싸여 있는 것과 같이 다른 장소에서 렌더링을 반환하는 동일한 함수를 호출하는 조건문이 있을 수 있습니다.

const parentFunc = () => {
    if(case==1)
        return function_a();
    if (case==2)
        return function_b();
}

function_a()는 useStyle() 또는 기타 어떤 훅을 생성하는 함수일 수 있습니다.

function_b()는 no 훅을 생성하는 함수일 수 있습니다.

여기서 parentFunc가 한쪽 훅을 렌더링하는 function_a()와 no 훅을 렌더링하는 function_b()를 반환하면 리액트는 동일한 렌더링 함수에서2개의 다른 렌더가1개 또는 1개의 훅을 사용하여1개 반환되고 다른1개의 훅을 사용하여1개의 훅이 반환된 것을 알립니다.에러 발생

더 적은 훅이 렌더링되었습니다.그리고 오류는 꽤 명백합니다.

대소문자가 반전되어 function_b()가 조건의 첫 번째 원인으로 반환되면 react는 같은 렌더 함수에서 다른 렌더링이 반환되었음을 알려주고 오류는 가 됩니다.

이전 렌더링보다 더 많은 후크를 렌더링했습니다.

솔루션:

create function_ab()과 같이 코드 플로우를 변경합니다.이 경우 사용되는 모든 훅이 해당 함수로 렌더링됩니다.

const function_ab = () => {
    if(case==1)
         return (<div></div>) //or whatever
    if(case==2)
         return (<div>I am 2 </div>) //or whatever
}

제 경우 다음과 같은 조건으로 내부에서 setState() 훅을 사용했기 때문에 해결 후에 오류가 발생하였습니다.리액트 훅 문서에 따르면 조건상 내부에서 훅을 사용하면 안 됩니다.

오류:

import React, { useState, useCallback } from 'react';
import './style.css';

export default function App() {
  const [count, setCount] = useState(0);
if(count < 10){
  return (
    <div>
      <h1>Hello Count!</h1>
        <button onClick={useCallback(setCount((count) => count + 1))}>
          click to add
        </button>
    </div>
  );
} else {
        return <div>Count reached 10!</div>
    }
 }

솔루션:

import React, { useState, useCallback } from 'react';
import './style.css';

export default function App() {
  const [count, setCount] = useState(0);
  const handleIncrement = useCallback(() => {
        setCount((count) => count + 1)
  })
  
if(count < 10){
return (
    <div>
      <h1>Hello Count!</h1>
      <button onClick={handleIncrement}>click to add</button>
    </div>
  );
} else {
        return <div>Count reached 10!</div>
    }
}

이 문제는onClick처럼setAllResultsVisible호출됩니다. 상태 변화를 트리거하고 모든 렌더링에 대해 결과를 생성합니다.

onClick={ setAllResultsVisible(!allResultsVisible) }

대신 함수 호출로 변경합니다.

onClick={_ => setAllResultsVisible(!allResultsVisible) }

컴포넌트를 반환하기 전에 후크를 사용해야 합니다.

언급URL : https://stackoverflow.com/questions/55622768/uncaught-invariant-violation-rendered-more-hooks-than-during-the-previous-rende

반응형