리 액트 후크는 componentWillUnmount에 대해서만 useEffect () 정리를 사용합니까?


84

내 문제를 쉽게 묻기 위해이 코드의 결과를 설명하겠습니다.

const ForExample = () => {
    const [name, setName] = useState('');
    const [username, setUsername] = useState('');

    useEffect(() => {
        console.log('effect');
        console.log({
            name,
            username
        });

        return () => {
            console.log('cleaned up');
            console.log({
                name,
                username
            });
        };
    }, [username]);

    const handleName = e => {
        const { value } = e.target;

        setName(value);
    };

    const handleUsername = e => {
        const { value } = e.target;

        setUsername(value);
    };

    return (
        <div>
            <div>
                <input value={name} onChange={handleName} />
                <input value={username} onChange={handleUsername} />
            </div>
            <div>
                <div>
                    <span>{name}</span>
                </div>
                <div>
                    <span>{username}</span>
                </div>
            </div>
        </div>
    );
};

ForExample component마운트는, '효과는'기록됩니다. 이것은 componentDidMount().

그리고 이름 입력을 변경할 때마다 '효과'와 '정리'가 모두 기록됩니다. 반대로 [username]두 번째 매개 변수를 추가했기 때문에 사용자 이름 입력을 변경할 때마다 메시지가 기록되지 않습니다 useEffect(). 이것은componentDidUpdate()

마지막으로 ForExample component마운트 해제시 'cleaned up'이 기록됩니다. 이것은 componentWillUnmount().

우리 모두 알고 있습니다.

요약하면 구성 요소가 다시 렌더링 될 때마다 '정리 됨'이 호출됩니다 (마운트 해제 포함).

이 구성 요소가 마운트 해제 된 순간 만 '정리 됨'으로 기록되도록하려면의 두 번째 매개 변수를로 변경하면 useEffect()됩니다 [].

그러나 만약 내가 변화 [username][], ForExample component더 이상 구현하는 componentDidUpdate()이름을 입력합니다.

내가하고 싶은 것은 구성 요소가 componentDidUpdate()이름 입력과 componentWillUnmount(). (구성 요소가 마운트 해제되는 순간에만 '정리 됨'로깅)


4
2 개의 개별 효과를 가질 수 있습니다. 하나는 username두 번째 인수로 배열이 제공 되고 하나는 두 번째 인수로 빈 배열이 제공됩니다.
Tholle

@Tholle 2 개의 별도 useEffect () 메서드를 만들어야한다는 뜻입니까?
koo

1
예, 그것이 그것에 대해 갈 수있는 한 가지 방법입니다.
Tholle

1
@Tholle 마지막 useEffect () 메서드에 의해 재정의 될 것이라고 생각했습니다. 시도 할게요. 감사합니다
koo

2
큰! 천만에요. 정리가 수행해야하는 작업에 따라 다릅니다. 2 개의 별도 효과는 나쁜 해결책이 아닙니다.
Tholle

답변:


82

정리가에 종속되지 않기 때문에 두 번째 인수로 빈 배열이 제공되는 username별도의 정리를 넣을 수 useEffect있습니다.

const { useState, useEffect } = React;

const ForExample = () => {
  const [name, setName] = useState("");
  const [username, setUsername] = useState("");

  useEffect(
    () => {
      console.log("effect");
    },
    [username]
  );

  useEffect(() => {
    return () => {
      console.log("cleaned up");
    };
  }, []);

  const handleName = e => {
    const { value } = e.target;

    setName(value);
  };

  const handleUsername = e => {
    const { value } = e.target;

    setUsername(value);
  };

  return (
    <div>
      <div>
        <input value={name} onChange={handleName} />
        <input value={username} onChange={handleUsername} />
      </div>
      <div>
        <div>
          <span>{name}</span>
        </div>
        <div>
          <span>{username}</span>
        </div>
      </div>
    </div>
  );
};

function App() {
  const [shouldRender, setShouldRender] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setShouldRender(false);
    }, 5000);
  }, []);

  return shouldRender ? <ForExample /> : null;
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>


멋지고 깨끗한 예. 그래도 궁금합니다. 변경된 탐색에 대해 어떻게 든 사용 효과를 트리거 할 수 있습니까? 아니면 구성 요소 트리에서 위로 이동해야합니까? "정리 된"useEffect를 붙여 넣을 때이 트리거가 표시되지 않기 때문입니다.
Fabian Bosler

113

하나 이상의 useEffect를 사용할 수 있습니다.

예를 들어 내 변수가 data1이면 내 구성 요소에서이 모든 것을 사용할 수 있습니다.

useEffect( () => console.log("mount"), [] );
useEffect( () => console.log("will update data1"), [ data1 ] );
useEffect( () => console.log("will update any") );
useEffect( () => () => console.log("will update data1 or unmount"), [ data1 ] );
useEffect( () => () => console.log("unmount"), [] );

4
첫 번째와 마지막 useEffect의 차이점은 무엇입니까? 첫 번째 useEffect는 willmount 또는 didmount 에서 호출되며 마지막 useEffect는 빈 배열로 콜백 함수를 반환했습니다. 각 useEffect 사용 사례를 언제 어떻게 사용할 수 있는지 자세히 설명해 주시겠습니까?
siluveru kiran kumar

3
@siluverukirankumar 콜백의 반환 값 (함수)은 destroy (unmount 이벤트)시 호출되는 것입니다. 그래서 마지막 예제는 즉시 함수를 반환하는 HOC입니다. 두 번째 매개 변수는 React가이 후크를 재실행하기 위해 변경 사항을 찾는 곳입니다. 빈 배열이면 한 번만 실행됩니다.
Georgy

3
감사합니다 @Georgy 마지막 useEffect 콜백하지 분명하게 볼 반환 그것을 가지고
siluveru 키란 쿠마르

2
따라서 useEffect 후크를 만들고 함수를 반환하면 .. 반환 된 함수 이전의 코드는 componentDidMount ...로 실행되고 반환 된 함수의 코드는 componentWillUnmount? 약간 혼란 스럽기 때문에 내가 올바르게 이해했는지 확인하십시오. useEffect (() => {// 마운트시 실행할 코드 ... return () => {// dismount를 실행할 코드}}) 맞습니까?
Maiya

overreacted.io/a-complete-guide-to-useeffect를 읽는 것이 좋습니다 . 라이프 사이클에서 후크에 대해 생각하는 것은 그리 달콤하지 않습니다
moto

2
function LegoComponent() {

  const [lego, setLegos] = React.useState([])

  React.useEffect(() => {
    let isSubscribed = true
    fetchLegos().then( legos=> {
      if (isSubscribed) {
        setLegos(legos)
      }
    })
    return () => isSubscribed = false
  }, []);

  return (
    <ul>
    {legos.map(lego=> <li>{lego}</li>)}
    </ul>
  )
}

위 코드에서 fetchLegos 함수는 promise를 반환합니다. useEffect 범위에 조건을 지정하여 프라 미스를 "취소"하여 컴포넌트가 마운트 해제 된 후 앱이 상태를 설정하지 못하도록 할 수 있습니다.

경고 : 마운트 해제 된 구성 요소에서 React 상태 업데이트를 수행 할 수 없습니다. 이것은 작동하지 않지만 응용 프로그램의 메모리 누수를 나타냅니다. 수정하려면 useEffect 정리 함수에서 모든 구독 및 비동기 작업을 취소하세요.


0

useEffect는 자체 범위 내에서 격리되고 그에 따라 렌더링됩니다. https://reactjs.org/docs/hooks-custom.html의 이미지

여기에 이미지 설명 입력


솔루션에 대한 링크는 환영하지만 답변이없는 경우 유용한 지 확인하십시오 . 링크 주변에 컨텍스트를 추가 하여 동료 사용자가 그것이 무엇인지, 왜 거기에 있는지 알 수 있도록 한 다음 페이지에서 가장 관련성이 높은 부분을 인용하십시오. 대상 페이지를 사용할 수없는 경우 다시 연결합니다. 링크에 불과한 답변은 삭제 될 수 있습니다 .
Богдан Опир

0

너무 많은 복잡한 함수와 메서드를 만드는 대신 이벤트 리스너를 만들고 수동으로 수행하는 것에 대해 걱정할 필요없이 자동으로 마운트 및 마운트 해제를 수행합니다. 여기에 예가 있습니다.

//componentDidMount
useEffect( () => {

    window.addEventListener("load",  pageLoad);

    //component will unmount
    return () => {
       
        window.removeEventListener("load", pageLoad);
    }

 });

이제이 부분이 완료되었으므로 이와 같이 pageLoad 함수에서 원하는 것을 실행합니다.

const pageLoad = () =>{
console.log(I was mounted and unmounted automatically :D)}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.