현재 버전

클래스형 컴포넌트와 다르게 함수형 컴포넌트는 라이프사이클 함수가 없습니다. 그렇다보니 useEffect()로 비슷하게 구현하여 사용합니다. 보통은 다음 처럼 사용합니다. 반드시 deps가 빈 배열 ([]) 이여야합니다.

useEffect(() => {
  console.log('componentDidMount')
  return () => console.log('componentWillMount')
}, [])

위와 같은 형식으로 document 또는 window 이벤트를 사용할 경우 보통은 다음 처럼 사용합니다.

useEffect(() => {
  const handler =  (event) => {
    // scroll event
  }
  window.addEventListener('scroll', handler)
  return () => window.removeEventListener('scroll', handler)
}, [])

handler 함수를 useEffect() 내부에 선언하는 이유는 react의 함수형 컴포넌트는 상태가 변경될때마다 컴포넌트 함수 전체를 다시 실행합니다. 그러므로 함수형 컴포넌트 내부에서 선언한 변수/함수는 상태 변경시 마다 새로운 함수를 정의합니다.  예를 들면 다음과 같습니다.

function TestComponent() 
  const [message, setMessage] = useState('initial message')
  const handler = () => console.log('recreate')
  return <button type="button" onClick={() => setMessage("nothing")}>{message}</button>
}

위의 TestComponent는 처음 렌더링시에 handler 함수가 생성되고 버튼을 클릭해서 상태가 변경되면  다시 렌더링되면서 또 다시 handler 함수가 생성됩니다. 즉 TestComponent가 2번 실행되고 handler 함수도 두번 만들어집니다. 그러므로 handler 함수의 레퍼런스 값이 처음과 달라지게 됩니다.

useState, useRef, useCallback, useMemo, useEffect 등과 같은 대다수의 use로 시작하는 함수들은 렌더링마다 함수/값을 실행 또는 만들지 않고 이전 함수/값을 되돌려주거나 특정 조건에 의해서만 다시 만들거나 실행합니다.

이 같은 이유로 addEventListener, removeEventListener에 전달하는 handler 함수는 반드시 useEffect 내부에 선언하거나 useCallback를 사용하거나 하는등 늘 처음에 정의한 함수 그대로여야하고 다시 정의된 함수가 아니여야합니다.

보통 실수로 외부로 빼면 문제가되는건 addEventListener가 아닌 removeEventListener가 됩니다. 컴포넌트가 ummount되었는데도 scroll 이벤트가 제거되지 않아 에러가 발생할 수 있습니다.





수정 이력

2021-02-02 08:43:44 에 아래 내용에서 변경 됨 #3

클래스형 컴포넌트와 다르게 함수형 컴포넌트는 라이프사이클 함수가 없습니다. 그렇다보니 useEffect()로 비슷하게 구현하여 사용합니다. 보통은 다음 처럼 사용합니다. 반드시 deps가 빈 배열 ([]) 이여야합니다.

useEffect(() => {
  console.log('componentDidMount')
  return () => console.log('componentWillMount')
}, [])

위와 같은 형식으로 document 또는 window 이벤트를 사용할 경우 보통은 다음 처럼 사용합니다.

useEffect(() => {
  const handler =  (event) => {
    // scroll event
  }
  window.addEventListener('scroll', handler)
  return () => window.removeEventListener('scroll', handler)
}, [])

handler 함수를 useEffect() 내부에 선언하는 이유는 react의 함수형 컴포넌트는 상태가 변경될때마다 컴포넌트 함수 전체를 다시 실행합니다. 그러므로 함수형 컴포넌트 내부에서 선언한 변수/함수는 상태 변경시 마다 새로운 함수를 정의합니다.  예를 들면 다음과 같습니다.

function TestComponent() 
  const [message, setMessage] = useState('initial message')
  const handler = () => console.log('recreate')
  return <button type="button" onClick={() => setMessage("nothing")}>{message}</button>
}

위의 TestComponent는 처음 렌더링시에 handler 함수가 생성되고 버튼을 클릭해서 상태가 변경되면  다시 렌더링되면서 또 다시 handler 함수가 생성됩니다. 즉 TestComponent가 2번 실행되고 handler 함수도 두번 만들어집니다. 그러므로 handler 함수의 레퍼런스 값이 처음과 달라지게 됩니다.

useState, useRef, useCallback, useMemo, useEffect 등과 같은 대다수의 use로 시작하는 함수들은 렌더링마다 함수/값을 실행 또는 만들지 않고 이전 함수/값을 되돌려주거나 특정 조건에 의해서만 다시 만들거나 실행합니다.

이 같은 이유로 addEventListener, removeEventListener에 전달하는 handler 함수는 반드시 useEffect 내부에 선언하거나 useCallback를 사용하거나 하는등 늘 처음에 정의한 함수 그대로여야하고 다시 정의된 함수가 아니여야합니다.

보통 실수로 외부로 빼면 문제가되는건 addEventListener가 아닌 removeEventListener가 됩니다. 컴포넌트가 ummount되었는데도 scroll 이벤트가 제거되지 않아 에러가 발생할 수 있습니다.

그리고 새롭게 작성하신 코드로 보면 useRef를 사용할 필요가 없어 보입니다.




2021-02-02 08:42:53 에 아래 내용에서 변경 됨 #2

클래스형 컴포넌트와 다르게 함수형 컴포넌트는 라이프사이클 함수가 없습니다. 그렇다보니 useEffect()로 비슷하게 구현하여 사용합니다. 보통은 다음 처럼 사용합니다. 반드시 deps가 빈 배열 ([]) 이여야합니다.

useEffect(() => {
  console.log('componentDidMount')
  return () => console.log('componentWillMount')
}, [])

위와 같은 형식으로 document 또는 window 이벤트를 사용할 경우 보통은 다음 처럼 사용합니다.

useEffect(() => {
  const handler =  (event) => {
    // scroll event
  }
  window.addEventListener('scroll', handler)
  return () => window.removeEventListener('scroll', handler)
}, [])

handler 함수를 useEffect() 내부에 선언하는 이유는 react의 함수형 컴포넌트는 상태가 변경될때마다 컴포넌트 함수 전체를 다시 실행합니다. 그러므로 함수형 컴포넌트 내부에서 선언한 변수/함수는 상태 변경시 마다 새로운 함수를 정의합니다.  예를 들면 다음과 같습니다.

function TestComponent() 
  const [message, setMessage] = useState('initial message')
  const handler = () => console.log('recreate')
  return <button type="button" onClick={() => setMessage("nothing")}>{message}</button>
}

위의 TestComponent는 처음 렌더링시에 handler 함수가 생성되고 버튼을 클릭해서 상태가 변경되면  다시 렌더링되면서 또 다시 handler 함수가 생성됩니다. 즉 TestComponent가 2번 실행되고 handler 함수도 두번 만들어집니다. 그러므로 handler 함수의 레퍼런스 값이 처음과 달라지게 됩니다.

useState, useRef, useCallback, useMemo, useEffect 등과 같은 대다수의 use로 시작하는 함수들은 렌더링마다 함수/값을 실행 또는 만들지 않고 이전 함수/값을 되돌려주거나 특정 조건에 의해서만 다시 만들거나 실행합니다.

이 같은 이유로 addEventListener, removeEventListener에 전달하는 handler 함수는 반드시 useEffect 내부에 선언하거나 useCallback를 사용하거나 하는등 늘 처음에 정의한 함수 그대로여야하고 다시 정의된 함수가 아니여야합니다.

만약 보통 실수로 외부로 빼면 문제가되는건 addEventListener가 아닌 removeEventListener가 됩니다. 컴포넌트가 ummount되었는데도 scroll 이벤트가 제거되지 않아 에러가 발생할 수 있습니다.

그리고 새롭게 작성하신 코드로 보면 useRef를 사용할 필요가 없어 보입니다.




2021-02-02 08:42:34 에 아래 내용에서 변경 됨 #1

클래스형 컴포넌트와 다르게 함수형 컴포넌트는 라이프사이클 함수가 없습니다. 그렇다보니 useEffect()로 비슷하게 구현하여 사용합니다. 보통은 다음 처럼 사용합니다. 반드시 deps가 빈 배열 ([]) 이여야합니다.

useEffect(() => {
  console.log('componentDidMount')
  return () => console.log('componentWillMount')
}, [])

위와 같은 형식으로 document 또는 window 이벤트를 사용할 경우 보통은 다음 처럼 사용합니다.

useEffect(() => {
  const handler =  (event) => {
    // scroll event
  }
  window.addEventListener('scroll', handler)
  return () => window.removeEventListener('scroll', handler)
}, [])

handler 함수를 useEffect() 내부에 선언하는 이유는 react의 함수형 컴포넌트는 상태가 변경될때마다 컴포넌트 함수 전체를 다시 실행합니다. 그러므로 함수형 컴포넌트 내부에서 선언한 변수/함수는 상태 변경시 마다 새로운 함수를 정의합니다.  예를 들면 다음과 같습니다.

function TestComponent() 
  const [message, setMessage] = useState('initial message')
  const handler = () => console.log('recreate')
  return <button type="button" onClick={() => setMessage("nothing")}>{message}</button>
}

위의 TestComponent는 처음 렌더링시에 handler 함수가 생성되고 버튼을 클릭해서 상태가 변경되면  다시 렌더링되면서 또 다시 handler 함수가 생성됩니다. 즉 TestComponent가 2번 실행되고 handler 함수도 두번 만들어집니다. 그러므로 handler 함수의 레퍼런스 값이 처음과 달라지게 됩니다.

useState, useRef, useCallback, useMemo, useEffect 등과 같은 대다수의 use로 시작하는 함수들은 렌더링마다 함수/값을 실행 또는 만들지 않고 이전 함수/값을 되돌려주거나 특정 조건에 의해서만 다시 만들거나 실행합니다.

이 같은 이유로 addEventListener, removeEventListener에 전달하는 handler 함수는 반드시 useEffect 내부에 선언하거나 useCallback를 사용하거나 하는등 늘 같은 처음에 정의한 함수 그대로여야하고 다시 정의된 함수가 아니여야합니다.

만약 보통 실수로 외부로 빼면 문제가되는건 addEventListener가 아닌 removeEventListener가 됩니다. 컴포넌트가 ummount되었는데도 scroll 이벤트가 제거되지 않아 에러가 발생할 수 있습니다.

그리고 새롭게 작성하신 코드로 보면 useRef를 사용할 필요가 없어 보입니다.