Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

coding etude

[React(Ts)] useEffect 가 작동하지 않을때... 본문

카테고리 없음

[React(Ts)] useEffect 가 작동하지 않을때...

코코리니 2024. 3. 13. 03:07

useEffect를 사용하여 값의 변경을 시도할 때 변경해야 할 값이 Array 또는 object 일때

간혹 useState의 setter 함수를 사용해서 값을 변경 했음에도 useEffect가 작동 하지 않을 때가 있다.

아래 예시가 작동하지 않는 예시이다.

function example() {
	const [arr, setArr] = useState<number[]>([]);
    
    //useEffect 가 동작하지 않음.
    useEffect(() => {
    	console.log(arr);
    },[arr]);
    
    function onChangeArr(e:React.ChangeEvent<생략>):void {
    	e.preventDefault();
        let newData:number[] = arr;
        newData.push(e.target.value);
        setArr(newData);
    }
    
    return(
    	// 생략
    )
}

분명 위 예시에서 setArr을 호출해서 값을 변경했음에도 useEffect가 작동하지 않는다.

이유는 크게 3가지중 하나이다.

1. onChange 함수에서 로직이 잘못되어 setArr이 동작 하지 않는경우

2. useState를 사용할 때 상태변경의 불변성을 유지하지 못한 경우

3. 간혹 React 내에서 랜더링의 최적화를 위하여 useEffect를 호출 하지 않는 경우(결국은 종속성의 문제.)

 

위의 얘시는 2번 에러에 속한다.

 

보통의 값을 경울 새로운 배열을 만들어서 넣는다고 생각하지만,  javascript에서는 값을 비교할 때 객체를 참조하여 값을 비교하는데

위의 예시의 경우 값이 같더라도 같은 객체를 참조하는지 알 수 없기 때문에 setter를 사용하였음에도 값의 불변성이 유지 되지 않아서 useEffect가 작동하지 않는것이다.

 

쉽게 설명하자면 newData는 함수가 실행 될때마다 계속 새로 만들어 지기 때문에 arr의 값이 같더라도 내부적으로는 새로운 arr이 만들어져서 setArr에 전달 되는것이기 때문에 상태값이 계속 새로운 값으로 들어와 불변성이 깨진것이라고 볼수 있다...(설명이 어려울 수있다.)

 

그레서 newData를 생성 할 때에는 arr이 새로 생성되는 것이 아닌 기존의 arr을 가져와서 사용해야 하는 것이다.

 

다음은 불변성을 유지한 예시 코드이다.

function example() {
	const [arr, setArr] = useState<number[]>([]);
    
    //useEffect 가 동작하지 않음.
    useEffect(() => {
    	console.log(arr);
    },[arr]);
    
    function onChangeArr(e:React.ChangeEvent<생략>):void {
    	e.preventDefault();
        setArr(preData => {
        	let newData = [...preData, e.target.value]
            return newData;
        });
    }
    
    return(
    	// 생략
    )
}

위의 예시처럼 훅의 setter 내부에서 newData를 만들어서 사용하면 동일한 값을 참조 하기 때문에 불변성이 유지되는 것이다.

state 값을 변경 할때는 불변성을 유지하는 가장 기초적인 문제였다고 생각된다. 

 

끝!