React Hooks에서 componentWillMount ()를 사용하는 방법은 무엇입니까?


175

React의 공식 문서에서는 다음과 같이 언급합니다.

React 클래스 라이프 사이클 메소드에 익숙하다면 useEffect Hook를 componentDidMount, componentDidUpdate 및 componentWillUnmount 결합으로 생각할 수 있습니다.

내 질문은-어떻게 우리는 어떻게 componentWillMount()lifecyle 방법을 후크에서 사용할 수 있습니까?

답변:


336

당신은 기존의 라이프 사이클 방법 (어떤 사용할 수 없습니다 componentDidMount, componentDidUpdate, componentWillUnmount후크에 등). 클래스 구성 요소에서만 사용할 수 있습니다. 그리고 후크를 사용하면 기능적 구성 요소에서만 사용할 수 있습니다. 아래 줄은 React 문서에서 나온 것입니다.

당신이 클래스 수명주기 방법 반응에 익숙하다면, 당신은 생각할 수 useEffect로 후크 componentDidMount, componentDidUpdatecomponentWillUnmount결합.

기능 구성 요소의 클래스 구성 요소에서 이러한 수명주기 방법을 모방 할 수 있습니다.

componentDidMount구성 요소가 마운트 될 때 내부 코드 가 한 번 실행됩니다. useEffect이 동작에 해당하는 후크는

useEffect(() => {
  // Your code here
}, []);

두 번째 매개 변수 (빈 배열)를 확인하십시오. 한 번만 실행됩니다.

두 번째 매개 변수없으면useEffect 구성 요소의 모든 렌더링 에서 후크가 호출되어 위험 할 수 있습니다.

useEffect(() => {
  // Your code here
});

componentWillUnmount이벤트 리스너 제거, 타이머 취소 등과 같은 정리에 사용됩니다. 아래와 같이 이벤트 리스너를 추가 componentDidMount하고 제거 한다고 가정하십시오 componentWillUnmount.

componentDidMount() {
  window.addEventListener('mousemove', () => {})
}

componentWillUnmount() {
  window.removeEventListener('mousemove', () => {})
}

위 코드와 동등한 후크는 다음과 같습니다.

useEffect(() => {
  window.addEventListener('mousemove', () => {});

  // returned function will be called on component unmount 
  return () => {
    window.removeEventListener('mousemove', () => {})
  }
}, [])

184
다른 Lifecycle 이벤트에 대한 좋은 설명이지만 componentWillMount ()의 대안에 대한 질문은 아닙니다.
쉬라즈

3
PanResponder 예제에서 componentWillMount가 필요한 것 같습니다. 그렇지 않으면 정의되지 않은 panHandler가 나타납니다.
Dror Bar

2
나는 이제 그 useEffect()기능을 정말로 이해한다 . 고마워.
Iharob Al Asimi

67
이것이 왜 받아 들여지는 대답입니까? 당신을위한 후크 상당 언급하지 않았다componentWillMount
Mykybo

3
@techexpert이 질문은에 해당하는 것이 componentWillMount아니라 componentWillUnmount. 이 답변은 실제로 질문에 전혀 대답하지 않으며 OP가 이미 암시 한 내용을 반복합니다.
JoshuaCWebDeveloper

62

useComponentDidMount 후크

대부분의 경우에 useComponentDidMount 사용할 도구입니다. 컴포넌트가 마운트 된 후 (초기 렌더링) 한 번만 실행됩니다.

 const useComponentDidMount = func => useEffect(func, []);

useComponentWillMount

클래스 구성 요소 componentWillMount는 레거시로 간주됩니다. 구성 요소가 마운트되기 전에 코드를 한 번만 실행해야하는 경우 생성자를 사용할 수 있습니다. 여기에 대한 자세한 내용 . 기능적 구성 요소에는 생성자와 같은 기능이 없으므로 구성 요소를 마운트하기 전에 후크를 사용하여 코드를 한 번만 실행하면 특정 경우에 적합합니다. 사용자 정의 후크로 달성 할 수 있습니다.

const useComponentWillMount = func => {
  const willMount = useRef(true);

  if (willMount.current) {
    func();
  }

  willMount.current = false;
};

그러나 함정이 있습니다. 비동기 적으로 상태를 설정하는 데 사용하지 마십시오 (예 : 서버 요청 후. 초기 렌더링에 영향을 미치지 않을 것으로 예상 할 수 있음). 이러한 경우는useComponentDidMount .

데모

const Component = (props) => {
  useComponentWillMount(() => console.log("Runs only once before component mounts"));
  useComponentDidMount(() => console.log("Runs only once after component mounts"));
  ...

  return (
    <div>{...}</div>
  );
}

전체 데모


18
이것은 질문에 대답하고 이해하는 유일한 대답입니다. 감사합니다!
chumakoff

3
그것의 유일한 문제는 관련된 상태 업데이트로 인해 추가 렌더링을 얻는 것입니다. 대신 참조를 사용하면 추가 렌더링없이 원하는 동작을 얻을 수 있습니다.`const useComponentWillMount = func => {const willMount = useRef (true); useEffect (() => {willMount.current = false;}, []); if (willMount.current) {func (); }}; `
remix23

2
componentWillMount기반한 기능 구현 useEffect에는 두 가지 문제가 있습니다. 첫 번째는 기능적 구성 요소에 장착 수명주기가 없으며 구성 요소가 렌더링 된 후 두 후크가 모두 실행되므로 Runs only once before component mounts오해의 소지가 있다는 것입니다. 두 번째는 componentWillMount서버 렌더링에서 호출되지만 useEffect그렇지 않습니다. 많은 라이브러리는 UNSAFE_componentWillMount현재 부작용이 서버 측을 트리거하는 유일한 방법이기 때문에 여전히 의존합니다 .
Paolo Moretti

2
@PaoloMoretti, 감사합니다. 이 componentWillMount 후크는 클래스 구성 요소의 componentWillMount 수명주기와 정확히 일치하지 않습니다. 그러나 전달 된 함수는 처음 호출 될 때만 즉시 실행됩니다. 이것은 실제로 렌더링되기 전에 실행되고 처음으로 값을 반환하기 전에 실행된다는 것을 의미합니다. 우리는 그것에 동의 할 수 있습니까? componentWillMount라는 이름을 사용하는 것이 이상적이지 않다는 데 동의합니다.이 이름은 클래스 수명주기 버전에서 특정 의미를 갖기 때문입니다. 아마도 "useRunPreMount"라고 부르는 것이 좋습니다.
벤 잉어

1
@PaoloMoretti, 나는 그것을 얻지 못한다. 나는 SSR과 함께 일하지 않지만, SSR component에서 WillMount는 서버와 클라이언트에서 한 번 두 번 실행된다는 것을 이해하고 있습니다. useComponentDidMount에 전달 된 콜백에 대해서도 마찬가지입니다. useComponentDidMount는 useEffect를 중계하여 콜백 호출을 중지합니다. useEffect의 콜백이 실행될 때까지 구성 요소의 기능은 서버에서 한 번, 클라이언트에서 한 번 두 번 실행됩니다. 그렇지 않습니까?
벤 잉어

53

reactjs.org에 따르면 componentWillMount는 향후 지원되지 않을 것입니다. https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

componentWillMount를 사용할 필요가 없습니다.

구성 요소가 마운트되기 전에 무언가를 수행하려면 constructor ()에서 수행하십시오.

네트워크 요청을하려면 componentWillMount에서 수행하지 마십시오. 이렇게하면 예기치 않은 버그가 발생하기 때문입니다.

componentDidMount에서 네트워크 요청을 수행 할 수 있습니다.

도움이 되길 바랍니다.


08/03/2019에 업데이트 됨

componentWillMount를 요청하는 이유는 렌더링 전에 상태를 초기화하려고하기 때문일 수 있습니다.

useState에서 수행하십시오.

const helloWorld=()=>{
    const [value,setValue]=useState(0) //initialize your state here
    return <p>{value}</p>
}
export default helloWorld;

또는 아마도 원래 코드가 다음과 같은 경우 componentWillMount에서 함수를 실행하려고 할 수 있습니다.

componentWillMount(){
  console.log('componentWillMount')
}

후크를 사용하면 라이프 사이클 방법을 제거하기 만하면됩니다.

const hookComponent=()=>{
    console.log('componentWillMount')
    return <p>you have transfered componeWillMount from class component into hook </p>
}

useEffect에 대한 첫 번째 답변에 무언가를 추가하고 싶습니다.

useEffect(()=>{})

useEffect는 모든 렌더에서 실행되며 componentDidUpdate, componentDidMount 및 ComponentWillUnmount의 조합입니다.

 useEffect(()=>{},[])

useEffect에 빈 배열을 추가하면 구성 요소가 마운트 될 때만 실행됩니다. useEffect가 전달한 배열을 비교하기 때문입니다. 따라서 빈 배열 일 필요는 없으며 변경되지 않는 배열 일 수도 있습니다. 예를 들어 [1,2,3] 또는 [ '1,2'] 일 수 있습니다. useEffect는 여전히 구성 요소가 마운트 된 경우에만 실행됩니다.

한 번만 실행하거나 매 렌더링 후에 실행하는지 여부에 따라 다릅니다. 수행중인 작업을 알고있는 한 배열을 추가하는 것을 잊어 버린 경우 위험하지 않습니다.

후크 샘플을 만들었습니다. 그것을 확인하시기 바랍니다.

https://codesandbox.io/s/kw6xj153wr


21/08/2019에 업데이트 됨

위의 답변을 쓴 이후로 백인이었습니다. 주의를 기울여야 할 것이 있습니다. 사용할 때

useEffect(()=>{},[])

react는 배열 []에 전달한 값을 비교할 때 Object.is ()를 사용하여 비교합니다. 객체를 전달하면

useEffect(()=>{},[{name:'Tom'}])

이것은 정확히 다음과 같습니다 :

useEffect(()=>{})

Object.is ()가 객체를 비교할 때 값 자체가 아닌 참조를 비교하기 때문에 매번 다시 렌더링됩니다. 참조가 다르기 때문에 {} === {}가 false를 반환하는 이유와 동일합니다. 여전히 참조 자체가 아닌 객체 자체를 비교하려면 다음과 같이 할 수 있습니다.

useEffect(()=>{},[JSON.stringify({name:'Tom'})])

17
문제는 훅으로 구현하는 방법이었습니다
Shubham Khatri

3
그러나 지원되지 않으므로 후크로 구현할 필요가 없습니다. 갈고리로하는 방법을 배울 필요가 없습니다.
MING WU

1
componentDidMount가 사용하기에 올바른 라이프 사이클이라고 언급
했으므로

8
확실히 이것이 정답이어야합니다. 후크 패러다임에서 ComponentWillMount를 사용할 수 없음을 설명합니다. 기능적 구성 요소의 초기화가 단순화되었습니다 – 기능의 일부일 필요가 있습니다
Shiraz

1
componentWillMount와 어떻게 같은가요? 함수형 구성 요소에 코드를 던지면 구성 요소를 마운트하려고 할 때뿐만 아니라 모든 단일 렌더링이 실행됩니다.
오버 코딩

13

useLayoutEffect[]기능이 실제로 다음과 비슷한 경우 빈 옵저버 세트 ( ) 로이를 수행 할 수componentWillMount . 첫 번째 내용이 DOM에 도달하기 전에 실행됩니다. 실제로 두 가지 업데이트가 있지만 화면에 그리기 전에 동기화됩니다.

예를 들면 다음과 같습니다.


function MyComponent({ ...andItsProps }) {
     useLayoutEffect(()=> {
          console.log('I am about to render!');
     },[]);

     return (<div>some content</div>);
}

useState이니셜 라이저 / 세터와 의 이점 useEffect은 렌더 패스를 계산할 수는 있지만 사용자가 알 수있는 DOM에 대한 실제 재 렌더링은 없으며 첫 번째 주목할만한 렌더링 전에 실행 됩니다.useEffect . 단점은 물론 화면에 페인팅하기 전에 확인 / 업데이트가 수행되어야하기 때문에 첫 번째 렌더링에서 약간의 지연이 있습니다. 그러나 실제로는 사용 사례에 따라 다릅니다.

개인적으로 생각 useMemo하면 무거운 것을해야하는 틈새 시장에서는 괜찮습니다. 명심할 한 예외는 표준입니다.


3
useLayoutEffect가가는 길입니다 !!!! 이것은 사용자가 로그인했는지 확인하는 것과 관련하여 내 질문에 대답합니다. (문제는 구성 요소가로드 된 다음 사용자가 로그인했는지 확인하는 것이 었습니다.) 내 질문은 그래도 표준 관행입니까? 너무 많은 곳에서 보지 못했습니다
Jessica

1
예, 꽤 흔합니다. 공식 React 문서에서도 언급되었습니다-사용자가 알기 전에 논리를 실행하기 위해 이중 DOM 렌더링의 결과로 인해 작은 텍스트로 표시됩니다.
rob2d

실제로 컴포넌트를 렌더링 한 후에 실행됩니다. 따라서 componentWillMount와는 완전히 다릅니다.
Jiri Mihal

7

이것은 useRef후크를 사용하여 기능 구성 요소에서 생성자를 시뮬레이션하는 방법입니다 .

function Component(props) {
    const willMount = useRef(true);
    if (willMount.current) {
        console.log('This runs only once before rendering the component.');
        willMount.current = false;        
    }

    return (<h1>Meow world!</h1>);
}

수명주기 예제는 다음과 같습니다.

function RenderLog(props) {
    console.log('Render log: ' + props.children);
    return (<>{props.children}</>);
}

function Component(props) {

    console.log('Body');
    const [count, setCount] = useState(0);
    const willMount = useRef(true);

    if (willMount.current) {
        console.log('First time load (it runs only once)');
        setCount(2);
        willMount.current = false;
    } else {
        console.log('Repeated load');
    }

    useEffect(() => {
        console.log('Component did mount (it runs only once)');
        return () => console.log('Component will unmount');
    }, []);

    useEffect(() => {
        console.log('Component did update');
    });

    useEffect(() => {
        console.log('Component will receive props');
    }, [count]);


    return (
        <>
        <h1>{count}</h1>
        <RenderLog>{count}</RenderLog>
        </>
    );
}
[Log] Body
[Log] First time load (it runs only once)
[Log] Body
[Log] Repeated load
[Log] Render log: 2
[Log] Component did mount (it runs only once)
[Log] Component did update
[Log] Component will receive props

물론 클래스 구성 요소에는 Body단계 가 없으므로 기능과 클래스의 개념이 다르기 때문에 1 : 1 시뮬레이션을 수행 할 수 없습니다.


나는 당신의 예를 들어 보지 않았지만 첫 번째 코드 스 니펫이 나를 위해 일합니다. 감사합니다!
SAndriy

6

첫 렌더링 전에 함수를 한 번 실행하는 사용자 지정 후크를 작성했습니다.

useBeforeFirstRender.js

import { useState, useEffect } from 'react'

export default (fun) => {
  const [hasRendered, setHasRendered] = useState(false)

  useEffect(() => setHasRendered(true), [hasRendered])

  if (!hasRendered) {
    fun()
  }
}

용법:

import React, { useEffect } from 'react'
import useBeforeFirstRender from '../hooks/useBeforeFirstRender'


export default () => { 
  useBeforeFirstRender(() => {
    console.log('Do stuff here')
  })

  return (
    <div>
      My component
    </div>
  )
}

3

componentDidMountcomponentWillUnmount함께 구현하는 좋은 해결 방법이 있습니다 useEffect.

설명서에 따라 useEffect"정리"기능을 반환 할 수 있습니다. 이 함수는 첫 번째 useEffect호출에서 호출되지 않고 후속 호출에서만 호출됩니다.

따라서 useEffect의존성이없는 후크를 사용하면 구성 요소를 마운트 할 때만 후크가 호출되고 구성 요소를 마운트 해제 할 때 "정리"기능이 호출됩니다.

useEffect(() => {
    console.log('componentDidMount');

    return () => {
        console.log('componentWillUnmount');
    };
}, []);

정리 리턴 함수 호출은 구성 요소가 마운트 해제 된 경우에만 호출됩니다.

도움이 되었기를 바랍니다.


2
componentWillMount 와 관련이없는 경우 어떻게 도움이 됩니까? 뭔가 빠졌습니까?
ZenVentzi

예, 당신은 같은에 사실 누락 useEffect호출하면 동일한 기능을 얻을 componentWillMount하고 componentWillUnmount멋지고 깨끗한 방법
AfikDeri

사실이 아니며, useEffect렌더링 후에 만 ​​실행 componentWillMount되고 구성 요소가 렌더링되기 전에 실행됩니다.
오버 코딩

@Overcode 나는 말하지 componentDidMount않았다 componentWillMount. 나는 그 질문에서 그것을 놓쳤다.
AfikDeri

1

useMemo 후크를 해킹하여 componentWillMount 수명주기 이벤트를 모방 할 수 있습니다. 그냥 해:

const Component = () => {
   useMemo(() => {
     // componentWillMount events
   },[]);
   useEffect(() => {
     // componentWillMount events
     return () => {
       // componentWillUnmount events
     }
   }, []);
};

상태와 상호 작용하기 전에 useMemo 후크를 유지해야합니다. 이것은 의도 된 방식이 아니지만 모든 componentWillMount 문제에 효과적이었습니다.

이것은 useMemo가 실제로 값을 리턴 할 필요가없고 실제로이를 다른 값으로 사용할 필요가 없기 때문에 작동하지만 한 번만 실행되는 종속성 ( "[]")과 컴포넌트의 맨 위에있는 종속성을 기반으로하는 값을 기억하기 때문입니다. 구성 요소가 다른 것보다 먼저 마운트 될 때 한 번 실행됩니다.


0

https://reactjs.org/docs/hooks-reference.html#usememo

useMemo에 전달 된 함수는 렌더링 중에 실행됩니다. 렌더링하는 동안 일반적으로하지 않는 작업은 수행하지 마십시오. 예를 들어 부작용은 useMemo가 아니라 useEffect에 속합니다.


usememo는 성능 최적화를위한 것입니다. 소품이 변경되면 이미 장착 된 후 후크가 다시 렌더링되어 저자의 목적을 상실합니다.
max54

0

벤 잉어의 대답은 나에게 유효한 것 같습니다.

그러나 우리가 기능적인 방법을 사용하고 있기 때문에 또 다른 접근 방식은 폐쇄 및 HoC의 이점을 얻을 수 있습니다

const InjectWillmount = function(Node, willMountCallback) {
  let isCalled = true;
  return function() {
    if (isCalled) {
      willMountCallback();
      isCalled = false;
    }
    return Node;
  };
};

그런 다음 사용하십시오 :

const YourNewComponent = InjectWillmount(<YourComponent />, () => {
  console.log("your pre-mount logic here");
});

0

원래 질문에 대한 짧은 대답 , componentWillMountReact Hooks와 함께 사용 하는 방법 :

componentWillMount되어 사용되지 않으며 기존의 생각 . 반응 추천 :

일반적으로 state를 초기화하기 위해 constructor ()를 사용하는 것이 좋습니다.

이제 후크 FAQ 에서 함수 구성 요소에 대한 클래스 생성자에 해당하는 내용을 확인하십시오.

생성자 : 함수 구성 요소에는 생성자가 필요하지 않습니다. useState 호출에서 상태를 초기화 할 수 있습니다. 초기 상태를 계산하는 것이 비싸면 useState에 함수를 전달할 수 있습니다.

따라서 사용 예는 componentWillMount다음과 같습니다.

const MyComp = () => {
  const [state, setState] = useState(42) // set initial value directly in useState 
  const [state2, setState2] = useState(createInitVal) // call complex computation

  return <div>{state},{state2}</div>
};

const createInitVal = () => { /* ... complex computation or other logic */ return 42; };

0

사용중인 빈 의존성 배열을 추가하기 만하면 효과가 componentDidMount있습니다.

useEffect(() => {
  // Your code here
  console.log("componentDidMount")
}, []);

0

시뮬레이션 할 수있는 간단한 트릭있다 componentDidMountcomponentWillUnmount사용은 useEffect:

useEffect(() => {
  console.log("componentDidMount");

  return () => {
    console.log("componentWillUnmount");
  };
}, []);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.