React 강제 Rerendering 하기

2022. 2. 7. 23:52Technology[Front]

React는 HTML과 달리 서버로 작동하고 데이터 갱신도 새로고침이 아닌 Rerendering을 통해 데이터무결성을 실현합니다. 그런데 종종 데이터가 갱신되었음에도 React가 관리하는 데이터가 아니거나 Rerendering의 조건을 충족하지 못해 Rerendering이 이루어지지 않아서 데이터 갱신이 되지 않는 경우가 있는데 이때에는 강제로 Rerendering할 필요성이 존재합니다.

클래스형(class) 컴포넌트의 경우 this.forceUpdate() 구문을 통해 손쉽게 Rerendering을 구현할 수 있지만 함수형(function) 컴포넌트의 경우 지원하지 않기 때문에 다른 방법으로 Rerendering을 구현해야합니다. 그 중에서 가장 보편적인 방법이 useState를 이용하여 해당 데이터가 변경될 때 React는 데이터 무결성을 위해 스스로 Rerendering을 실행하므로 목적을 달성할 수 있습니다.

(1) React

const Comments = ({ match ,history }) => {
  var html = ''
  const [ data, setData ] = useState({});
  useEffect(() => {
    axios
      .post("http://localhost:8088/allreply", null, {
        params: {
          BOARDNO : urlparams[1]
        }
      })
      .then((response) => {
        for(let i = 0; i < response.data.length; i++) {
          console.log(response.data[i]);
          html += `<div class="${response.data[i].cnumber}">`
          html += `<a class='author'>${response.data[i].idmanage.userid}</a>`
          html += `<div class='metadata'><div>${response.data[i].cdate}</div></div>`;
          html += `<div class='text'>${response.data[i].ccontent}</div>`;
          if(urlparams[0] == response.data[i].idmanage.id) {
            html += `<button class="midify_reply ${response.data[i].cnumber}">수정하기</button>`;
            html += `<button class="check_reply ${response.data[i].cnumber}">전송하기</button>`;
            html += `<button class="delete_reply ${response.data[i].cnumber}">삭제하기</button><br>`;
          }
          html += `</div>`
        }
        $('#reply').html(html);
        $('.check_reply').hide();

        $('#replybutton').on('click', () => {
          
          //id가 replybutton인 태그의 click이벤트 발생 시 실행할 코드
          
            for(let i = 0; i < 5 ; i++) {
              setData({
                ...data,
                count : count
              })
            }
          }
        })
  
        $(".check_reply").on('click', (e) =>  {
        
            //id가 check_reply인 태그의 click이벤트 발생 시 실행할 코드
            
            for(let i = 0; i < 5 ; i++) {
              setData({
                ...data,
                count : count
              })
            }
        })
  
        $(".delete_reply").on('click', (e) =>  {
        
            //id가 delete_reply인 태그의 click이벤트 발생 시 실행할 코드
            
            for(let i = 0; i < 5 ; i++) {
              setData({
                ...data,
                count : count
              })
            }
        })  
      })
  }, [data]);
  
      return(
      //HTML 코드 작성 부분
      )
}

위의 코드는 실제 프로젝트에서 일부 발췌한 내용이라 실제 구현 시 각 상황에 맞게 수정해서 사용하시면 됩니다. 함수형 컴포넌트인 Comments는 강제 Rerendering을 할 때 this.forceUpdate() 구문을 사용할 수 없으므로 의미 없는 데이터를 저장하는 data를 const [ data, setData ] = useState({}); 로 정의하게 되면 이제부터 data라는 데이터는 React가 데이터 무결성을 지키기 위해 관리하는 데이터가 됩니다. 해당 data의 값을 변경할 때에는 반드시 setData()메소드를 이용해 수정해야 React가 Rerendering을 수행합니다. 이후 useEffect(()=>{}, [])를 이용해 두 번째 인자로 입력하는 배열에 data를 입력하시면 data가 변경되었을 때 변경을 React가 감지한 후 첫 번째 인자로 입력한 메소드를 스스로 실행시킵니다. 그래서 useEffect의 첫 번째 인자로 제공하는 함수는 반복수행해야할 필요성이 있는(데이터 갱신이 필요한) 부분을 입력하시고 두 번째 인자로 제공하는 배열에는 앞서 선언한 의미없는 데이터 data를 주시고 데이터 갱신이 필요할 때마다 setData를 이용해 data값을 변경시키면 스스로 React가 data의 변경을 감지해서 useEffect의 첫 번째 인자로 제공하는 함수를 반복실행합니다. 위의 코드에서는 id가 replybutton인 html 태그와 class가 check_reply, delete_reply인 html 태그를 클릭할 시 for문으로 setData를 5번씩 실행시키고 있으며(1번만 실행 시 제대로 Rerendering이 되지 않는 경우가 종종 존재하여 2~5번 정도 반복실행시키길 추천드립니다.) 이로써 React는 Rerendering하고 useEffect의 첫 번째 인자로 제공한 함수를 다시 실행시킵니다.

마지막으로 setData 실행하실 때 주의하실 점은 data의 단순한 값만 변경하게 되면 data가 참조하는 값이 동일하므로 React가 변경으로 인식하지 못해서 Rerendering하지 않는 경우가 발생할 수 있으니 되도록이면 새로운 객체로 변경하시거나 { ...data, 'key' : value } 형식으로 기존 data의 객체와 새로운 key - value 를 더한 새로운 객체로 변경하는 방법을 추천드립니다. 

이상으로 이번 게시글에서는 React의 함수형 컴포넌트에서 강제로 Rerendering을 하는 방법에 대해 알아보았습니다.