
useEffect,useCallback,useMemo등
의존성 배열을 파라미터로 받는React Hooks은
의존성 배열의 모든 값들의종속성(참조 값)을 비교해서
다르다면 첫번째 파라미터로 받은 함수를 동작시킨다고 한다.실제로 Object.is() - MDN 메서드를 사용한다고한다.
=== 보다 엄격한 Object.is[JavaScript] Object Methods - Object.is()
원시 타입은 불변성을 가지고 있기 때문에 상관없다.
객체 타입은heap영역에 실제 값이 저장되어있고
call stack에 저장되어 있는 것은 실제 값의 참조 값이다.그렇기 때문에 객체의 속성 값를 바꿔도 참조 값은 바뀌지 않기 때문에
Hook이 동작하지 않아야 한다.즉, 새로운 객체가 식별자에 할당되어야만
Hook이 동작한다.
하지만 그렇지 않다.
의존성 배열에 객체를 넣으면모든 행위에서Hook이 동작한다고 한다.
왜 그런지 이유를 알고 싶었는데 모듈 동작 구조를 까보는데 실패했다..
[React] React Hooks 실제 선언 위치예를 들어 객체의 속성을 변경해도 Hook이 동작한다.
번외로 이 코드는 한 가지 문제점이 존재한다.
클릭하세요버튼을 클릭하면 count 값이 1 증가하는데
useEffect의 의존성 배열에는 user 만 있음에도 실행된다.개발자 모드
index.js 의 <React.StrictMode>에서는
초기 렌더링시에useEffect가 두번 동작 한다.배포 환경에서는 한번만 동작하니 넘어가길 바란다.
아니면 태그를 없애서 확인하길 바란다.import React, { useState, useEffect } from "react"; export default function App() { const [count, setCount] = useState(0); const user = { name: "Narcoker", age: 100 }; const handleButton = () => { setCount((prevCount) => prevCount + 1); }; useEffect(() => { console.log("참조 값이 변경되면 실행합니다."); }, [user]); return ( <> <h1>{count}</h1> <button onClick={handleButton}>클릭하세요</button> </> ); }
React의 컴포넌트는 State나 Props가 변경되면 즉시 재렌더링된다.
App() 함수가 처음부터 다시 실행된다는 의미이다.즉, 변수의 값이 재생성 됨에 따라 참조값이 바뀌게 된다.
따라서 user 의 참조값이 바뀌기 때문에 useEffect가 실행이 되는 것이다.참고로 hook들도 다시 선언된다.
하지만 내부적으로 상태값을 가지고 있으며
내부 메커니즘을 통해서 이 상태값은 유지가 된다.
객체 자체가 아닌 변경될 객체의 속성의 식별자를 의존성 배열에 삽입한다.
useEffect(() => { console.log("참조 값이 변경되면 실행합니다."); }, [user.name]);
객체를 JSON 문자열 값으로 변환하여 사용한다.
useEffect(() => { console.log("참조 값이 변경되면 실행합니다."); }, [user.name]);
._isEqual(prev, next)
Kent C.Dodds가 개발한 라이브러리이다.
의존성 배열의 값들의 변경을 확인할때깊은 비교를 한다.사용 시
객체와객체를 가지고 있는 배열만 의존성 배열에 추가하라고한다.
함수를 포함하는 객체는 의존성 배열에 넣으면 안된다고 한다.
의존성 배열에 추가하면 안되는 형태const objectHasFunction = { func: () => {} }; useDeepCompareEffect(() => { console.log("함수를 가진 객체는 사용하지 말것"); }, [objectHasFunction]);
잘 동작하는 예제import React, { useState } from "react"; import useDeepCompareEffect from "use-deep-compare-effect"; export default function App() { const [count, setCount] = useState(0); const user = { name: "Narcoker", age: 100, parent: { child: {} } }; const handleButton = () => { setCount((prevCount) => prevCount + 1); }; useDeepCompareEffect(() => { console.log("참조 값이 변경되면 실행합니다."); }, [user]); return ( <> <h1>{count}</h1> <button onClick={handleButton}>클릭하세요</button> </> ); }