source

Is there a way to check if the react component is unmounted?

manycodes 2023. 2. 22. 22:49
반응형

Is there a way to check if the react component is unmounted?

I have a usecase where i need to unmount my react component. But in some cases, the particular react component is unmounted by a different function. Hence, I need to check if the component is mounted before unmounting it.

부터isMounted()는 공식적으로 권장되지 않습니다.이 작업은 컴포넌트에서 수행할 수 있습니다.

componentDidMount() { 
  this._ismounted = true;
}

componentWillUnmount() {
   this._ismounted = false;
}

이 패턴은 당신 자신의 것을 유지하는 것이다.state변수는 React에 자세히 설명되어 있습니다.JS 문서: isMounted는 Antiattern입니다.

상태를 갱신할 때마다 리액션이 컴포넌트 전체를 재렌더하고 useEffect 등의 훅 실행을 트리거하기 때문에 마운트 여부를 확인하기 위해 후크를 사용하는 것이 좋습니다.

function MyComponent(props: Props) {
  const isMounted = useRef(false)

  useEffect(() => {
    isMounted.current = true;
    return () => { isMounted.current = false }
  }, []);

  return (...);
}

export default MyComponent;

컴포넌트에 다음 컴포넌트가 장착되어 있는지 확인합니다.if (isMounted.current) ...

Shubham의 답변은 코드 전환이 필요한 사람들을 위해 리액션에 의해 제안되는 회피책이라고 생각합니다.isMounted안티패턴

이것이 반드시 나쁘다고는 할 수 없지만, 이 문제에 대한 진정한 해결책을 제시할 가치가 있습니다.

Shubham이 링크한 기사는 이 안티 패턴을 피하기 위한 두 가지 제안을 제공한다.필요한 것은 컴포넌트가 마운트 해제되었을 때 setState를 호출하는 이유에 따라 달라집니다.

컴포넌트에서 Flux 스토어를 사용하는 경우 componentWillUnmount에서 구독을 취소해야 합니다.

class MyComponent extends React.Component {
  componentDidMount() {
    mydatastore.subscribe(this);
  }
  render() {
    ...
  }
  componentWillUnmount() {
    mydatastore.unsubscribe(this);
  }
}

ES6 약속을 사용할 경우 취소할 수 있도록 약속을 포장해야 할 수 있습니다.

const cancelablePromise = makeCancelable(
  new Promise(r => component.setState({...}}))
);

cancelablePromise
  .promise
  .then(() => console.log('resolved'))
  .catch((reason) => console.log('isCanceled', reason.isCanceled));

cancelablePromise.cancel(); // Cancel the promise

자세한 것은 이쪽makeCancelable를 참조해 주세요.

결론적으로 변수를 설정하고 컴포넌트가 마운트되었는지 확인하여 이 문제에 패치를 적용하려고 하지 말고 문제의 근원으로 이동하십시오.다른 일반적인 케이스가 있으면 코멘트 부탁드립니다.

또 다른 솔루션으로는 Refs를 사용하는 방법이 있습니다.React 16.3+를 사용하는 경우 렌더링 기능에서 최상위 항목을 참조합니다.

그런 다음 ref.current가 null인지 확인합니다.

예:

class MyClass extends React.Component {
  constructor(props) {
    super(props);
    this.elementRef = React.createRef();
  }

  checkIfMounted() {
     return this.elementRef.current != null;
  }

  render() {
    return (
      <div ref={this.elementRef} />
    );
  }
}

@DerekSoike의 답변을 사용하지만, 제 경우에는useState국가가 부활한 이후 기마 상태를 통제할 필요가 없어졌다

나에게 효과가 있었던 것은 단일 변수를 사용하는 것이었다.

myFunct호출되었다setTimeout같은 컴포넌트가 다른 페이지에서 훅을 초기화하면 메모리 누수가 다시 나타나는 상태가 부활한 것 같습니다.

그래서 이건 나한테 안 통했어

  const [isMounted, setIsMounted] = useState(false)

  useEffect(() => {
    setIsMounted(true)
    return () => setIsMounted(false)
  }, [])

  const myFunct = () => {
    console.log(isMounted) // not always false
    if (!isMounted) return
    // change a state
  }

그리고 이건 나한테 효과가 있었어

  let stillMounted = { value: false }
  useEffect(() => {
    stillMounted.value = true
    return () => (stillMounted.value = false)
  }, [])

  const myFunct = () => {
    if (!stillMounted.value) return
    // change a state
  }

내가 여기 온 이유는 이 일을 멈출 방법을 찾고 있었기 때문이다.pollingAPI를 사용합니다.

리액트 문서는 다음 사항을 다룹니다.websocket투표용지는 제외합니다.

내가 일하는 방식으로는

// React component

React.createClass({
    poll () {
        if (this.unmounted) {
            return
        }
        // otherwise, call the api
    }
    componentWillUnmount () {
        this.unmounted = true
    }
})

그건 효과가 있다.도움이 되었으면 좋겠다

이 테스트에 불합격하는 사례가 있으면 알려주세요=]

후크를 사용하는 경우:

function MyComponent(props: Props) {
  const [isMounted, setIsMounted] = useState<boolean>(false);

  useEffect(() => {
    setIsMounted(true);
  }, []);

  useEffect(() => {
    return () => {
      setIsMounted(false);
    }
  }, []);

  return (...);
}

export default MyComponent;

같은 아이디어이지만 다른 구현

/**
 * component with async action within
 * 
 * @public
 */
class MyComponent extends Component {
    constructor ( ...args ) {
        // do not forget about super =)
        super(...args);
        // NOTE correct store "setState"
        let originSetState = this.setState.bind(this);
        // NOTE override
        this.setState = ( ...args ) => !this.isUnmounted&&originSetState(...args);
    }
    /**
     * no necessary setup flag on component mount
     * @public
     */
    componentWillUnmount() {
        // NOTE setup flag
        this.isUnmounted = true;
    }
    /**
     *
     * @public
     */
    myCustomAsyncAction () {
        // ... code
        this.setState({any: 'data'}); // do not care about component status
        // ... code
    }

    render () { /* ... */ }
}

핫 새로고침으로 해결하고 다양한 it 이벤트에 대응합니다✅

   const {checkIsMounted} = useIsMounted(); //hook from above
   useEffect(() => {
    //here run code
    return () => {
      //hot reload fix
      setTimeout(() => {
        if (!checkIsMounted()) {
          //here we do unmount action 
        }
      }, 100);
    };
  }, []); 

문제

useState() 훅 사용 시 문제가 발생하였습니다.useEffect 함수로 다른 작업을 수행하려고 하는 경우(예:fetching some data컴포넌트가mounted)를 동시에 설정합니다.new value갈고리에 걸기 때문에

const [isMounted, setIsMounted] = useState(false)

useEffect(() =>
{
    setIsMounted(true) //should be true

    const value = await fetch(...)

    if (isMounted) //false still
    {
        setValue(value)
    }

    return () => 
    {
        setIsMounted(false)
    }
}, [])

훅 유언의 가치remain the same초기값(false)으로 표시됩니다(거지로 변경해도 마찬가지).그것은 변하지 않을 것이다.first render새로운 값을 적용하기 위해 새로운 재검색이 필요합니다.어떤 이유로 @GWorking 솔루션도 동작하지 않았습니다.데이터를 가져오는 동안 간격이 발생하는 것처럼 보이므로 데이터가 도착했을 때 구성 요소는 이미 마운트 해제되어 있습니다.

솔루션

그냥 하면 돼combine both컴포넌트가 마운트 해제되었는지 확인합니다.any re-render사용방법separate컴포넌트가 다음 컴포넌트인지 여부를 추적하는 변수still그 사이에 말뚝에 올라타다render time period

const [isMounted, setIsMounted] = useState(false)
let stillMounted = { value: false }

useEffect(() =>
{
    setIsMounted(true)
    stillMounted.value = true

    const value = await fetch(...)

    if (isMounted || stillMounted.value) //isMounted or stillMounted
    {
        setValue(value)
    }

    return () => 
    {
        (stillMounted.value = false)
    
        setIsMounted(false)
    }
}, [isMounted]) //you need to also include Mounted values

그게 도움이 됐으면 좋겠네요!

경고를 피할 수 있는 간단한 방법이 있습니다.

마운트 해제된 구성 요소에서 반응 상태 업데이트를 수행할 수 없습니다.이것은 no-op이지만, 애플리케이션의 메모리 누수를 나타내고 있습니다.수정하려면 componentWillUnmount 메서드에서 모든 구독 및 비동기 작업을 취소합니다.

재정의할 수 있습니다.setState다음 패턴을 사용하여 클래스 컴포넌트 내의 메서드를 지정합니다.

    componentWillUnmount() {
        this._unmounted = true;
    }

    setState(params, callback) {
        this._unmounted || super.setState(params, callback);
    }

구성 요소가 마운트 해제되는 것을 발견했습니다. 이 변수를 채우십시오.

if(!this._calledComponentWillUnmount)this.setState({vars});

다음을 사용할 수 있습니다.

myComponent.updater.isMounted(myComponent)

"myComponent"는 반응 구성요소의 인스턴스입니다.구성 요소가 장착되어 있으면 '참'을 반환하고, 장착되어 있지 않으면 '거짓'을 반환합니다.

  • 이 방법은 지원되지 않습니다.componentWillUnmount의 비동기/이벤트 등록을 해제하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/39767482/is-there-a-way-to-check-if-the-react-component-is-unmounted

반응형