LECTURE/React

React rendering

heywoo 2023. 4. 17. 14:02

리액트 랜더링 

 아래 주석 안에 들어가는 모든 엘리먼트를 ReactDOM에서 관리하기 때문에 이것을 Root DOM node라고 부르다. 일반적으로 React로 구현된 애플리케이션은 하나의 루트 돔 노드가 있다.

  단, 리액트를 기존 앱에서 통합하려는 경우에는 원하는 만큼의 독립된 루트 돔 노드를 가질 수도 있다.

React Element를 루트 DOM 노드에 렌더링 하려면
        ReactDOM.createRoot(루트 DOM 노드).render(렌더링 할 엘리먼트)로 처리하면 된다.

<body>

    <div id="root"></div> <!-- 루트 돔 노드-->
    
    <script type="text/babel">

        const element = (
            <>
                <h1>What time is it now?</h1>
                <h3>It is { new Date().toLocaleTimeString() }</h3>
            </>
        );

        /* React Element를 루트 DOM 노드에 렌더링 하려면
        ReactDOM.createRoot(루트 DOM 노드).render(렌더링 할 엘리먼트)로 처리하면 된다. */
        ReactDOM.createRoot(document.getElementById('root')).render(element);

    </script>
</body>

 

리액트 엘리먼트는 불변 객체(immutable)이다.
        엘리먼트를 생성한 이후에는 해당 엘리먼트의 자식이나 속성을 변경할 수 없다.
        따라서 엘리먼트를 업데이트 하기 위해서는 완전히 새로운 엘리먼트를 만들고 다시 render를 호출해야 한다.

<body>

    <div id="root"></div> <!-- 루트 돔 노드-->
    
    <script type="text/babel">

        const ReactClientDOM = ReactDOM.createRoot(document.getElementById('root')); //한번만 일어나도록

        function tick() { //엘리먼트를 function 안에 작성, 이 함수를 1초에 한 번씩 부른다
            const element = (
            <>
                <h1>What time is it now?</h1>
                <h3>It is { new Date().toLocaleTimeString() }</h3>
            </>
             );

          ReactClientDOM.render(element); // element를 렌더링하는 동작은 초마다 일어나도록
       
        }

        tick(); //생성
        setInterval(tick, 1000); //1초에 한번씩 불러온다. 


    </script>


        1초 마다 tick 함수를 호출하여 새로운 엘리먼트를 생성하고 랜더링 한다.
        매 초마다 새로운 엘리먼트가 다시 랜더링 되지만 개발자 도구의 elements를 살펴보면
        실제 업데이트 되는 부분만 갱신 되는 것을 확인할 수 있다. 
        
        리액트 엘리먼트는 메모리 상에서 연산되는 가상의 돔으로, 실제 돔과 동일한 렌더 트리를 가지고 있다. (복제본)
        render 호출 시 새로운 렌더 트리를 만들고 가상의 돔과 비교 (diff 알고리즘) 후, 변화가 있는 부분만 실제 돔에 반영

          -> 돔에 대한 재구성을 많이 하지 않기 때문에 효율적이다

 

조건부 랜더링

  여러 개의 엘리먼트 중 특정 조건에 따라 하나의 엘리먼트만 랜더링 할 수 있다.  

<body>
    <div id="root"></div> 
    
    <script type="text/babel">
    
    const answer = parseInt(prompt('리액트가 재미 있으신가요? \n1. 재미있다. \n2. 어렵다.'));

    1. 랜더링 시 조건 비교 후 조건부 랜더링 

    const positiveElement = <h1>앞으로 점점 더 재밌어 질 거 예요^^</h1>
    const negativeElement = <h1>천천히 앞의 내용을 복습해보세요^^</h1>

    ReactDOM.createRoot(document.getElementById('root'))
        .render((answer==1) ? positiveElement : negativeElement);



     2. JSX 내에서 조건부로 엘리먼트 생성 (보편적)
     2-1. if문 

     let element;
     if(element === 1) {
         element = <h1>앞으로 점점 더 재밌어 질 거 예요^^</h1>;
     } else {
         element = <h1>천천히 앞의 내용을 복습해보세요^^</h1>;
    }
    
    ReactDOM.createRoot(document.getElementById('root')).render(element);



     2-2. 삼항연산자 (if 보다 많이 쓰인다)

     const element = (answer === 1) ? (
         <h1>앞으로 점점 더 재밌어 질 거 예요^^</h1>
     ) : (
         <h1>천천히 앞의 내용을 복습해보세요^^</h1>
     );
     ReactDOM.createRoot(document.getElementById('root')).render(element);



     2-3. && 연산자를 이용한 조건부 엘리먼트 생성
     특정 조건을 만족하는 경우에만 랜더링을 하고, 그렇지 않은 경우엔 아무것도 보이지 않게 하고자 할 때 사용한다. 

const element = answer === 1 && <h1>앞으로 점점 더 재밌어 질 거 예요^^</h1>;

 ReactDOM.createRoot(document.getElementById('root')).render(element);


     주의 사항
    false 조건을 가지고 랜더링을 하는 경우 조건에 일치하지 않으면 랜더링 되는 요소가 없지만

    0과 같이 falsy한 값을 이용해 조건부 엘리먼트 생성을 하면 판단은 false지만 0을 반환한다.  


    const number = 0;
    const element = number && <h1>0이 아닙니다</h1>;
    
    ReactDOM.createRoot(document.getElementById('root')).render(element);
    </script>
    
    
</body>