❗️Rendering in React
React에서 함수 컴포넌트의 rendering = state, props를 기반으로 UI 요소를 그려내는 행위
렌더링의 결과물 = UI 요소(화면에 JSX 문법으로 무엇이 나타날지를 적어둔 컴포넌트들)
렌더링 결과물에 영향을 주는 요소는 = state, props
즉, input(state & props)에 따라 다른 output(UI)을 표현하는 함수(function)와도 구조적으로 동일
❗️side Effect
프로그래밍 측면에서의 side Effect는 함수가 어떤 동작을 할 때,
input - output 이외의 다른 값을 조작한다면, 이 함수에는 Side Effect(부수 효과) 가 있다고 표현
[예시]
let count = 0
function greetWithSideEffect(name) { // Input
count = count + 1 // Side Effect!
return `${name}님 안녕하세요!` // Output
}
greetWithSideEffect() 라는 함수는 이름을 받아 인삿말을 리턴하는 함수입니다.
하지만 이 함수는 단순히 input과 output만 존재하는 함수가 아닙니다.
실행하는 중간에 함수 외부 세계에 있는 count라는 변수를 조작합니다.
이는 함수의 결과값 이외의 다른 상태를 변경시키는 행위 에 해당하므로 Side Effect 가 있다고 할 수 있습니다.
함수 컴포넌트의 Side Effect는 state와 props를 받아서 UI를 그려내는 것 이외의 행위라고 할 수 있습니다.
그렇다면 함수 컴포넌트에서의 Side Effect는, 렌더링이 아니고 외부 세계에 영향을 주는 어떠한 행위입니다.
(Ex : Data Fetching, DOM에 직접 접근(ex. Event Listener 등록), 구독(ex. setInterval)과 같은 행위)
❌ side Effect들을 함수의 body 자리(render)에서 실행시키면 안됩니다.
함수 컴포넌트의 리턴 값은 UI 요소이고, state&props의 변화가 있을 때마다 함수가 실행됨
= 매 렌더링 때마다 함수 body에 있는 로직이 실행됨
또한 렌더링과 무관한 로직이 렌더링 과정에서 실행되기 때문에 렌더링 자체에 영향을 줘 성능 상 악영향을 끼칠 수도 있음
[예시]
function greetWithSideEffect({ name }) { //
// Bad!
document.title = `${name}님 안녕하세요!`; // Side Effect
return <div>{`${name}님 안녕하세요!`}</div>; // Output
}
❗️ 의존성 배열(Dependancy Array)
[예시]
import { useEffect } from 'react';
function greetWithSideEffect({ name }) { // Input
useEffect(() => {
// Good!
document.title = `${name}님 안녕하세요!`; // Side Effect
}, [name]);
return <div>{`${name}님 안녕하세요!`}</div>; // Output
}
import { useEffect } from "react"
// 사용법
useEffect( 실행시킬 동작, [ 타이밍 ] )
document.addEventListener("타이밍", 실행시킬 동작) // 추상화 한 예시
// 매 렌더링마다 Side Effect가 실행되어야 하는 경우
useEffect(() => {
// Side Effect
})
// Side Effect가 첫 번째 렌더링 이후 한번 실행 되고,
// 이후 특정 값의 업데이트를 감지했을 때마다 실행되어야 하는 경우
useEffect(() => {
// Side Effect
}, [value])
// Side Effect가 첫 번째 렌더링 이후 한번 실행 되고,
// 이후 어떤 값의 업데이트도 감지하지 않도록 해야 하는 경우
useEffect(() => {
// Side Effect
}, [])
❗️ useEffect를 사용한 렌더링 사이클
❗️ clean up Effect
이전에 일으킨 Side Effect를 정리할 필요가 있을 때 사용
useEffect(() => {
function handleScroll() {
console.log(window.scrollY)
}
document.addEventListener("scroll", handleScroll)
}, [])
useEffect(() => {
function handleScroll() {
console.log(window.scrollY)
}
document.addEventListener("scroll", handleScroll)
return () => {
document.removeEventLisnter("scroll", handleScroll)
}
}, [])
❌ 주의할 점은 단순히 컴포넌트가 생성되고, 사라지는 시점에만 Cleanup Effect가 실행되는 건 아님
다음 Effect가 일어나기 전에, 이전 Effect의 영향을 정리해줘야 한다는 컨셉을 꼭 기억하기