React component, element, instance 끝내기(By. Boaz) 정리

혜혜·2023년 10월 17일
0

React

목록 보기
6/9
post-thumbnail

💡 해당 글은 유튜브 "가장 쉬운 웹개발 with Boaz"의 "React component, element, instance 끝내기"를 보고 정리한 글입니다. 문제 시 삭제합니다!

React component, element, instance 끝내기

💡 Managing the instances

🌟 Component, Element, Instance가 각각 무엇인지 정확하게 알고 있는 것이 중요하다!

📍 기존 UI model(OOP)

class Form extends TraditionalObjectOrientedView {
	render() {
    	// Read some data passed to the view
      	const { isSubmitted, buttonText } = this.attrs;
      
      	if(!isSubmitted && !this.button) {
        	// Form is not yet submitted. Create the button!
          	this.button = new Button({
            	children: buttonText,
              	color: 'blue'
            });
          	this.el.appendChild(this.button.el);
        }
      
      	if(this.button) {
        	// The button is visible. Update its text!
          	this.button.attrs.children = buttonText;
          	this.button.render();
        }
      
      	if(isSubmitted && this.button) {
        	// Form was submitted. Destroy the button!
          	this.el.removeChild(this.button.el);
          	this.button.destroy();
        }
      
      	if(isSubmitted && !this.message) {
        	// Form was submitted. Show the success message!
          	this.message = new Message({ text: 'Success!' });
          	this.el.appendChild(this.message.el);
        }
    }
}
  • button class component -> instance (각자 local state, own properties를 가짐)
  • isSubmittedthis.button, this.message 체크해서 각 children을 create, update, destory!

✔️ 한계점

  • Component가 많아지면, 각 Component에 속한 Instance들도 많아질 것
  • 각 Instance를 일일이 appendChild(), removeChild() 하는 코드를 계속 써주어야 함
  • Form Component 가 직접 button Component를 생성하고 있기 때문에, 두 Component는 서로 Decoupling 하기가 어렵다!

→ 이를 극복하기 위해 나온 게 Element!!

💡 Elements Describe the Trees

📍 Elements

  • DOM 트리에 그려질 것들을 묘사해 주는 역할을 함
  • DOM 노드에 대한 정보를 가지고 있는 plain object
  • React에게 어떤 것을 화면에 그려야 하는지 알려주는 것으로, Instance 가 아님
  • typeprops 라는 프로퍼티를 가짐
    (type: string | ReactClass, props: object)
  • type이 string일지 ReactClass일지는 Element 종류에 따라 달라짐

📍 React DOM elements

{
	type: 'button',
    props: {
    	className: 'button button-blue',
        children: {
        	type: 'b',
            props: {
            	children: 'OK!'
            }
        }
    }
}

<button class='button button-blue'>
	<b>
  		OK!
  	</b>
</button>
  • 여기서 type으로 지정된 'button'은 HTML 태그의 이름
  • 태그의 이름이 string이기 때문에, DOM element는 type이 string 값으로 들어감

📍 React Component elements

{
	type: Button,
    props: {
    	color: 'blue',
        children: 'OK!'
    }
}
  • 여기서의 Button은 string 아님

즉, DOM elementtype이 string이고,
Component elementtype이 ReactClass

  • DOM element든, Component element든 DOM 트리에게 전달할 정보를 담고 있음

Q. 그래서 이렇게 도입한 element로 어떻게 기존의 UI 모델링의 한계를 극복했는가?

  • 우리가 작성한 Component Element와 실제 DOM과 가장 가까운 정보를 가진 DOM Element같은 위계를 가질 수 있음!!
const DeleteAccount = () => ({
	type: 'div',
  	props: {
    	children: [{
        	type: 'p',
          	props: {
            	children: 'Are you sure?'
            }
        }, {
        	type: DangerButton,
          	props: {
            	children: 'Yep'
            }
        }, {
        	type: Button,
          	props: {
            	color: 'blue',
              	children: 'Cancel'
            }
        }]
    }
})

const DeleteAccount = () => (
	<div>
    	<p>Are you sure?</p>
  		<DangerButton>Yep</DangerButton>
  		<Button color='blue'>Cancel</Button>
    </div>
);
  • p, DangerButton, Button이 서로 완전히 decoupled가 가능해짐
  • div 태그 아래에 있는 typeButton인 객체에는 어떻게 create/update/destroy 되어야 하는지에 대한 정보 없음
    → 이건 Button Component 내부에 가지고 있는 것!!

💡 Components Encapsulate Element Trees

  • ComponentElement를 return하는 함수일 경우,
    Element는 DOM 트리에 리턴할 정보를 property에 가지고 있는 JavaScript 객체인데,
    그래서 위 코드처럼 트리 구조로 되어 있는 Element들은, DOM 트리에 전달할 정보만 캡슐화 되어 있다고 볼 수 있다!!
  • 언제 create/update/destroy 되는지는 React가 알아서 함
  • Component Element를 만났을 때 React는,
    Component에게 어떤 element를 return 하는지 물어봄
  • 그게 아래 있는 DOM element (여기에 DOM Tree에 어떤 정보를 알려줘야 하는지가 다 나와 있음)
{
	type: Button,
    props: {
    	color: 'blue',
        children: 'OK!'
    }
}

// React는 Button을 만나면 component에게 물어봐서 아래 DOM element를 return 받음
{
	type: 'button',
    props: {
    	className: 'button button-blue',
        children: {
        	type: 'b',
            props: {
            	children: 'OK!'
            }
        }
    }
}
  • 이렇게 타고 타고 내려간 element가 DOM element일 때까지 찾아가는 것!!
  • 이런 식으로 Element tree 순회
  • 모든 elements가 가진 DOM element를 알게 됨 → React가 해당 DOM element들을 적절한 때에 따로 create/update/destroy
  • 따라서 기존 UI modeling 을 아래와 같이 간단하게 구현할 수 있게 됨
const Form = ({ isSubmitted, buttonText }) => {
	if (isSubmitted) {
    	// Form submitted! Return a message element.
      	return {
        	type: Message,
          	props: {
            	text: 'Success!'
            }
        };
    }
  
  	// Form is still visible! Return a button element.
  	return {
    	type: Button,
      	props: {
        	children: buttonText,
          	color: 'blue'
        }
    };
};
  • React element를 활용하여, 기존의 DOM structure를 모두 활용하지 않고,
    필요한 정보만 독립적으로 UI를 관리할 수 있게 됨
  • Component가 return한 element를 활용해서 DOM Tree를 encapsulate!!

💡 Components Can Be Classes or Functions

  • 이 부분은 생략... (Functional component에서도 Class component의 기능을 대부분 사용할 수 있어서)

💡 Top-Down Reconciliation

🌟 Reconciliation은 다른 영상에서 더 자세히 다뤄주신다고... 여기서는 그냥 "리액트 컴포넌트에서 props나 state가 변경될 때, 직전에 렌더링된 element와 새로 반환된 element를 비교하여 실제 DOM을 업데이트 할지 말지 결정하게 되는데, 이때 두 element가 일치하지 않으면 새로운 요소로 DOM을 업데이트 하는 것" 정도로 이해하고 넘어가면 될듯...

ReactDOM.render({
	type: Form,
  	props: {
    	isSubmitted: false,
      	buttonText: 'OK!'
    }
}, document.getElementById('root'));
  • 위 함수 호출 시, React는 Form component에게 props를 전달하며 return element 요청
  • Form -> Button -> DOM node element(button) 순서로 return element 진행
// React: You told me this...
{
	type: Form,
    props: {
    	isSubmitted: false,
        buttonText: 'OK!'
    }
}

// React: ...And Form told me this...
{
	type: Button,
    props: {
    	children: 'OK!',
        color: 'blue'
    }
}

// React: ...and Button told me this! I guess I'm done.
{
	type: 'button',
    props: {
    	className: 'button button-blue',
        children: {
        	type: 'b',
            props: {
            	children: 'OK!'
            }
        }
    }
}
  • ReactDOM.render(), setState() 호출 시 React call reconciliation
  • reconciliation이 끝나면, React는 DOM tree의 결과물을 알게 됨
  • 이 Element tree를 renderer에게 전달하고, renderer는 실제 DOM에 이 변화를 적용
  • 위와 같은 점진적인 변화 덕분에 이러한 conciliation이 쉽게 최적화가 가능함!!
  • props가 immutable이면 change 계산이 더 빨라짐 (변하지 않으니까)
  • Class component가 결국 instance를 만들어주는 것 (직접 생성은 X)

💡 Summary

  • ElementDOM Tree 생성에 필요한 정보를 담은 object
  • React DOM node element & React Component element 두 종류
  • Element는 property로 다른 element를 가질 수 있음
  • DOM node와 component를 mixed, nested 가능하게 함
  • Component는 props → element 하는 function
  • 부모 Component가 return한 element의 type이 자식 Component 이름일 때, props는 해당 자식 Component의 input(prosp)이 됨 (props는 1 way flow)
  • Instance는 class component에서의 this
  • instance를 직접 생성할 필요 X -> React가 해 줌
  • React.createElement(), JSX, React.createFactory() -> return element
profile
쉽게만살아가면재미없어빙고

0개의 댓글