미발견 오류: 예상보다 적은 수의 후크가 렌더링되었습니다.리액트 훅의 우발적인 조기 반환 문구가 원인일 수 있습니다.
다음 컴포넌트에서 에이징 셀렉터를 누르고 값을 15로 변경하여 운전면허 필드 없이 폼을 렌더링하면 오류가 나타납니다.
Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
at invariant (react-dom.development.js:55)
at finishHooks (react-dom.development.js:11581)
at updateFunctionComponent (react-dom.development.js:14262)
at beginWork (react-dom.development.js:15103)
at performUnitOfWork (react-dom.development.js:17817)
at workLoop (react-dom.development.js:17857)
at HTMLUnknownElement.callCallback (react-dom.development.js:149)
at Object.invokeGuardedCallbackDev (react-dom.development.js:199)
at invokeGuardedCallback (react-dom.development.js:256)
at replayUnitOfWork (react-dom.development.js:17113)
at renderRoot (react-dom.development.js:17957)
at performWorkOnRoot (react-dom.development.js:18808)
at performWork (react-dom.development.js:18716)
at flushInteractiveUpdates$1 (react-dom.development.js:18987)
at batchedUpdates (react-dom.development.js:2210)
at dispatchEvent (react-dom.development.js:4946)
at interactiveUpdates$1 (react-dom.development.js:18974)
at interactiveUpdates (react-dom.development.js:2217)
at dispatchInteractiveEvent (react-dom.development.js:4923)
아래의 코드 예:
const {useState} = React;
function App() {
const [name, setName] = useState('Mary');
const [age, setAge] = useState(16);
if (age < 16) {
return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type="number"
onChange={e => {
setAge(+e.target.value);
}}
/>
</div>
);
}
const [license, setLicense] = useState('A123456');
return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type="number"
onChange={e => {
setAge(+e.target.value);
}}
/>
<br />
Driver License:{' '}
<input
value={license}
onChange={e => {
setLicense(e.target.value);
}}
/>
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
문제는 첫 번째 렌더링에서 3이useState후크가 호출되었습니다.name,age그리고.license하지만 나이가 16세 미만으로 바뀌면useState위해서license는 호출되지 않고 처음 2개의 훅만 호출됩니다.React docs 상태:
루프, 조건 또는 중첩된 함수에 Hooks를 호출하지 마십시오.대신, 항상 리액트 기능의 최상위 레벨에서 후크를 사용하십시오.를 사용하십시오.이 규칙을 따르면 구성 요소가 렌더링할 때마다 후크가 동일한 순서로 호출됩니다.이를 통해 React는 여러 시스템 간의 후크 상태를 올바르게 유지할 수 있습니다.
useState그리고.useEffect콜을 클릭합니다.
호출되는 후크의 순서는 중요합니다.후크가 호출되지 않도록 하는 코드를 쓰면 React는 후크콜과 그 값을 대조할 수 없습니다.
해결방법은 이 시스템을license필요 여부에 관계없이 호출할 수 있도록 함수의 맨 위에 연결합니다.
const {useState} = React;
function App() {
const [name, setName] = useState('Mary');
const [age, setAge] = useState(16);
const [license, setLicense] = useState('A123456');
return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type="number"
onChange={e => {
setAge(+e.target.value);
}}
/>
{age >= 16 && <span>
<br />
Driver License:{' '}
<input
value={license}
onChange={e => {
setLicense(e.target.value);
}}
/></span>
}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
리액트 훅의 순서를 변경하여 이 문제를 해결했습니다.
그래서 코드를 변경했습니다.
function(){
const [loading ,setLoading] = React.useState(false);
if(loading){
return "loading ....."
}
useEffect(()=>{
if(condition) {
doSomething();
}
}, []);
return <div>component</div>
}
로.
function(){
const [loading ,setLoading] = React.useState(false);
useEffect(()=>{
if(condition) {
doSomething();
}
}, []);
if(loading){
return "loading ....."
}
return <div>component</div>
}
따라서 로드가 true가 되면 useEffect가 실행되지 않고 오류가 발생합니다.그러나 useEffect 후에 JSX 요소 로드를 선언하면 완벽하게 동작합니다.
뛰지 않았는지 확인합니다.useEffect조건부로
예를 들어 다음과 같은 코드가 있는 경우:
if(condition) {
useEffect(()=>{
doSomething();
}, []);
}
그럼 으로 변경해 주세요.
useEffect(()=>{
if(condition) {
doSomething();
}
}, []);
그러면 오류가 발생하지 않습니다.
그래서 저도 이 에러는 발생했지만 후크가 감긴 상태와는 관련이 없습니다.대신 키 값이 안 좋아서 그런 거예요.
아이템을 드래그 앤 드롭으로 리스트에서 다른 리스트로 이동하는 컴포넌트가 있었습니다.다만, 그 중 몇 가지는 잠겨 있기 때문에, 그 요소내의 훅에 대한 참조를 삭제했을 뿐입니다.
문제는 인덱스를 키로 사용했기 때문에 위에 있는 새로운 요소를 드래그하면 잠긴 요소와 동일한 키가 나타나 ref 값이 변경되어 React가 위의 오류로 불만을 제기했다는 것입니다.
그래서 이 문제를 접하게 된 분들에 대한 저의 대답은, 여러분이 정말로 독특한 키를 가지고 있는지 확인해 보세요!
이 훅의 했습니다.후크 위치를 변경하여 수정했습니다.useEffect()함수의 중간에서 헤더로 이동합니다.그리고 후크 내부 루프를 사용하지 마십시오.
재렌더 간에 특정 값이 변경되지 않은 경우 효과를 적용하지 않도록 React에게 지시할 수 있습니다.이렇게 하려면 배열을 useEffect에 대한 두 번째 선택적 인수로 전달합니다.
useEffect( () => {
dispatch({type: 'GET_PAGE', slug: Param});
setPagedata( data );
});
로.
useEffect( () => {
dispatch({type: 'GET_PAGE', slug: Param});
}, [Param]);
useEffect( () => {
setPagedata( data );
}, [data]);
됐다!
조건부로 렌더링하는 경우 구성요소 속성 데이터를 중간에 넣지 마십시오.
if (splashScreen)
return <Spinner>Loading</Spinner>
//DO NOT PUT THEM HERE
return (
...
)
하였습니다.useCallback렌더링 컴포넌트(및 if 조건 내)에 후크합니다.후크를 기능하는 컴포넌트 외부로 이동하면 에러가 해결.교훈: 조건문 안에 후크를 사용하지 마십시오.
이 문제는 핫 새로고침(HMR)이 켜져 있고 useEffect를 추가 또는 삭제하는 경우에도 발생할 수 있습니다.페이지를 새로고침하기만 하면 에러는 재현되지 않습니다.
제 경우 use Window Dimensions 훅을 조건부로 기능 컴포넌트의 반환 부분에 직접 사용하고 있었습니다.반환 부분 외부에 변수를 선언하고 조건 렌더링에서 변수를 사용하여 해결합니다.이게 도움이 됐으면 좋겠네요!
언급URL : https://stackoverflow.com/questions/53472795/uncaught-error-rendered-fewer-hooks-than-expected-this-may-be-caused-by-an-acc
'programing' 카테고리의 다른 글
| my.cnf에 대한 Mysqltuner 제안 및 변경 사항 (0) | 2023.03.14 |
|---|---|
| WordPress에서 모든 게시물을 표시하는 방법 (0) | 2023.03.14 |
| 무한 스크롤 수동 트리거 (0) | 2023.03.14 |
| 각도가 있는 옵션 선택에서 공백 옵션 제거JS (0) | 2023.03.14 |
| React를 사용하여 현재 전체 URL을 읽으시겠습니까? (0) | 2023.03.14 |