programing

상위 상태가 변경될 때 구성 요소가 마운트 해제됨

prostudy 2022. 4. 5. 22:29
반응형

상위 상태가 변경될 때 구성 요소가 마운트 해제됨

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

반응형