상위 상태가 변경될 때 구성 요소가 마운트 해제됨
React 16.8.2를 사용하고 있는데 앱 구성 요소 상태가 변경될 때마다 구성 요소의 자녀가 마운트 해제되는 문제가 발생함
시나리오는 다음과 같다.
- 여러 상태 변수가 있는 App.jsx(기능 구성요소)가 있음(useState)
- 이러한 상태 변수 중 일부에 대한 세터는 컨텍스트 제공자를 통해 트리 아래로 전달된다(하위부의 컨텍스트 사용)
- 이러한 세터를 호출하는 메뉴 구성 요소(예: 모달 대화 상자 표시)가 있는 경우
- 모달 대화 상자 구성 요소(앱의 자식)가 있는데, 상태 변수를 속성으로 사용하여 열려 있는지 아닌지를 결정하는 -- 표준 Reacting that I think.
내 문제: 앱의 상태 변수가 변경될 때(물론 후크를 통해), 앱의 아이들은 변경되는 상태와 아무런 관련이 없더라도 마운트 해제되고 다시 마운트된다.그들은 단지 다시 태어난 것이 아니다 - 아이들은 마운트 해제되고 그들의 상태는 다시 초기화된다.예를 들어, 필드는 내 대화상자에서 지워져서는 안 되는 경우.
이것은 이미 상당히 복잡한 애플리케이션이기 때문에 나는 오늘 많은 시간을 문제를 분리하는데 보냈다.그리고 나서 나는 간단한 create-react-app을 설정해서 거기서 이 행동을 복제하려고 노력했다. 하지만 이 테스트 앱은 그렇게 행동한다.예비 콜백을 통해서든 또는 아동으로부터 맥락에서 제공한 콜백을 통해서든 상위 상태를 변경하는 것은 재렌더링하지만 마운트 해제/해제 및 아동 상태는 그대로 유지된다.
하지만 내 진짜 앱에서는 구성 요소 재마운트 및 하위 상태가 다시 초기화된다.
나는 내가 할 수 있는 한 최대한으로 단순화했다 - 나는 아이의 컨텍스트를 통해 "setFoo"로 가짜 상태 변수 "foo"를 설정하고 있다.foo는 어떤 구성 요소에서도 사용되지 않지만 foo의 값을 변경하면 앱의 하위 항목이 마운트 해제/마운트 해제된다.
App.jsx에서:
const App = props => {
const [foo, setFoo] = useState(false);
// ...
const appControl = {
toggleFoo: () => setFoo(!foo);
};
// ...
return (
<AppContext.Provider value={appControl}>
... a bunch of stuff not using foo anywhere
... including, deep down:
<Menu />
</AppContext.Provider>
);
};
메뉴.jsx:
const Menu = props => {
const appControl = useContext(AppContext);
// ...
return (
... super simplified for test
<div onClick={appControl.toggleFoo}>
Toggle Foo
</div>
);
};
만약 내가 상태를 제대로 이해한다면, 나는 상태를 바꾸는 것이 아이들을 다시 재입양시키지만, 다시 장착하지는 않는 결과를 초래해야 한다고 믿는다.이것은 내가 간단한 Create-react-app 테스트에서는 볼 수 있지만 실제 앱에서는 볼 수 없는 것이다.
최신 리액션을 수행하지 않은 것으로 확인됨 - 업그레이드로 해결하시겠습니까?
내가 뭘 잘못하고 있는지, 혹은 여기서 오해하고 있는지 통찰해줘서 고마워.
해결됐어. 이거 흥미로운데.이렇게 된 것이다.
내 앱 컴포넌트에는 HORK의 트리가 꽤 깊었다.나의 일부 의심스러운 결정 때문에, 나는 결국 앱을 두 개의 구성 요소로 나누게 되었다.App 및 AppCore.그럴 만한 이유가 있었는데, 새벽 3시 일리가 있는 것 같았다.하지만 빠르고 더러워지기 위해 앱코어를 앱 기능 안에 넣어두었다.나는 스스로 "이것이 어떤 문제를 일으킬지 궁금하다"고 생각했던 것을 기억한다.이제 나는 알고 있습니다.상수에 할당된 JSX와 직접 반환된 JSX 간의 차이를 잘 모르기 때문에 리액션 전문가가 이 문제를 충분히 설명할 수 있을 것이다.그러나 분명히 있고, 이것은 번식하기 간단하다.
테스트 앱을 생성-실행-응용하려면:
create-react-app test
cd test
그런 다음 App.js의 내용을 다음 항목으로 대체하십시오.
import React, { useState, useEffect } from "react";
const Menu = props => <div onClick={props.click}>Toggle Foo</div>;
const Test = props => {
useEffect(() => {
console.log("mounted");
return () => console.log("unmounted");
}, []);
return null;
};
const App = props => {
const [foo, setFoo] = useState(false);
// this is the root of the problem
// move this line outside of the function body
// and it mounts/unmounts correctly
const AppCore = props => <Test />;
return (
<>
<Menu click={() => setFoo(!foo)} />
<AppCore />
</>
);
};
export default App;
그런 다음 npm이 시작되며, "Toggle Foo"를 클릭하면 테스트 구성 요소가 마운트 해제/제거된 것을 볼 수 있다.
여기서 해결책은 단순히 AppCore를 기능 본체 밖으로 옮기는 것이다.내 진짜 앱에서, 이것은 내가 리팩토링 할 일이 있다는 것을 의미한다.
이것이 리액션 이슈로 간주될 수 있는지 궁금하다.
참조URL: https://stackoverflow.com/questions/55606873/component-unmounts-when-parent-state-changes
'programing' 카테고리의 다른 글
Vuetify: 색이 표시되지 않음 (0) | 2022.04.05 |
---|---|
Laravel 인증과 Vue-router를 함께 사용하는 방법 (0) | 2022.04.05 |
라우터 링크와 vue 및 vuetify 혼동 (0) | 2022.04.05 |
ngOnInit 내에서 구독자를 점화하지 않는 각도 재스민 테스트 (0) | 2022.04.05 |
반응 라우터가 매개 변수와 함께 작동하지 않음 (0) | 2022.04.05 |