좌충우돌 개발자의 길

[React] useEffect와 axios를 같이 사용할 때 무한루프 에러 해결하기 본문

STUDYING/React

[React] useEffect와 axios를 같이 사용할 때 무한루프 에러 해결하기

sustronaut 2022. 7. 24. 00:44

- 구현 목표 : 댓글을 쓰면 새로고침없이 댓글창이 바로 나올 수 있도록 바꾸는 기능 구현하기 (카톡처럼!)

- 내가 생각한 방법 : useEffect를 써서 comment가 새로 들어올 때마다 업데이트할수 있도록 짜자

import { useEffect, useState } from "react";
import axios from 'axios';

export default function useAxios(url) {
    const [data, setData] = useState([]);

    useEffect(() => {
        axios.get(url)
            .then(res => {
                return res.data.body;
            })
            .then(data => {
                setData(data);
            })
            .catch(error => {
                console.log(Error);
                alert("존재하지 않는 방명록입니다.")
                window.location.replace("/");
            });
    }, [data]);

    return data;
}

- 문제점 : 원하는 부분이 화면상에는 잘 구현되었지만 백엔드 터미널을 보니 무한 루프로 돌아가고 있었다.. 이 부분은 서버에 엄청난 악영향을 주는 것이라 빨리 이 부분을 해결해야했다.

 

- 해결방안 :  

1) 구글링으로 "useEffect axios 무한루프" 으로 검색하자 나와 같은 많은 사례들을 볼 수 있었다.

2) https://jacobgrowthstory.tistory.com/51?category=950812 에서 참고한 결과(정말 감사합니다ㅠㅠㅠㅠ) 내 무한루프의 원인은 useEffect 함수 내에서 setState함수를 호출했기 때문이었다. 즉 useEffect 실행 → setState 실행으로 state 변경 → useEffect 실행 (무한루프)

3) 종속성 배열로 해결하라는 말이 있었지만 내 기능 특성 상 댓글 전송시 실시간으로 화면에 보여줘야하는 기능을 구현했기에 이와 같은 해결은 처음 화면을 렌더링할때만 실행되어 맞지 않는 해결방안이었다.

4) setState를 useEffect 내부에 넣지않고 이벤트 함수에 넣어주는 방법을 택했다. 그래서 onSubmit함수와 댓글 불러오는 함수를 따로 두었던 부분을 아예 onSubmit함수안에 댓글 불러오는 axios를 넣기로 결정했다.

// 전송 버튼 함수
    function onSubmit(e) {
        e.preventDefault();

        // form input 값 없이 submit 금지 
        if (commentRef.current.value.length === 0) {
            alert("인사말을 입력해주세요!");
            return false;
        }

        axios.post(`/api/comment/${userId}`,
            {
                comment: commentRef.current.value
            },
            {
                headers: {
                    "Content-Type": "application/json",
                }
            }
        )
            .then(res => {
                commentRef.current.value = "";
                console.log("전송 성공");
                //window.location.replace(`/${userId}`);
            })
            .catch(res => { console.log('Error!', res) });
		
        //추가한 부분 (바로 axios로 댓글을 불러오는 코드다)
        axios.get(`/api/comment/${userId}`).then(res => {
            setComments(res.data.body);
        })
    };

 

 

이렇게 했더니 에러가 해결되었지만 또다른 복병이 있었다... 다음 글에서!