본문 바로가기

스터디/React

[React] 강의 7주차 (2) - React 원리

[국비지원교육]  [패스트캠퍼스] React 강의 7주차 (2) - React 원리

[Javascript] React 

-  함수 컴포넌트

- 클래스 컴포넌트

- virtual DOM

- 마법의 hook 원리와 제약


1.  함수 컴포넌트

[app.js]
/* @jsx createElement */
import { createDOM, createElement, render } from './react'

function Title(props){
    return <h1>{props.children}</h1>
}
function Item(props){
    return <li style={`color: ${props.color}`}>{props.children}</li>
}
const vdom = <p>
    <Title label="React">React 정말 잘 만들기</Title>
    <ul>
        <Item color="red">첫 번째 아이템</Item>
        <Item color="blue">두 번째 아이템</Item>
        <Item color="green">세 번째 아이템</Item>
    </ul>
</p>

render(vdom, document.querySelector('#root'))


[react.js]

export function createDOM(vdom){
    if(typeof vdom === 'string') {
        return document.createTextNode(vdom);
    }
    const element = document.createElement(vdom.tag);

    Object.entries(vdom.props)
        .forEach(([name, value]) => element.setAttribute(name, value));

    vdom.children
        .map(createDOM)
        .forEach(element.appendChild.bind(element));

    return element;
}

export function createElement(tag, props, ...children){
    props = props || {};
    
    if(typeof tag === 'function'){
        if(children.length > 0){
            return tag({
                ...props,
                children: children.length === 1 ? children[0] : children
            })
        } else {
            return tag(props);
        }
        
    } else {
        return { tag, props, children }
    }   
    
}

export function render(vdom, container){
    container.appendChild(createDOM(vdom));
}

 

2. 클래스 컴포넌트

[app.js]
/* @jsx createElement */
import { createElement, render, Component } from './react';

class Title extends Component {
    render(){ 
        return <h1>{ this.props.children }</h1>
    }
}
function Item(props){
    return <li style={`color: ${props.color}`}>{props.children}</li>
}
const App = () => <p>
    <Title label="React">React 정말 클래스 컴포넌트 잘 만들기</Title>
    <ul>
        <Item color="red">첫 번째 아이템</Item>
        <Item color="blue">두 번째 아이템</Item>
        <Item color="green">세 번째 아이템</Item>
    </ul>
</p>

render(<App />, document.querySelector('#root'))



[react.js]

export class Component {
    constructor(props){
        this.props = props;
    }
}

export function createDOM(vdom){
    if(typeof vdom === 'string') {
        return document.createTextNode(vdom);
    }
    const element = document.createElement(vdom.tag);

    Object.entries(vdom.props)
        .forEach(([name, value]) => element.setAttribute(name, value));

    vdom.children
        .map(createDOM)
        .forEach(element.appendChild.bind(element));

    return element;
}
function makeProps(props, children){
    return {
        ...props,
        children: children.length === 1 ? children[0] : children
    }
}

export function createElement(tag, props, ...children){
    props = props || {};
    
    if(typeof tag === 'function'){
        if(tag.prototype instanceof Component){
            const instance = new tag(makeProps(props, children))
            return instance.render();
        } else {
            if(children.length > 0){
                return tag(makeProps(props, children));
            } else {
                return tag(props);
            }
        }
        
    } else {
        return { tag, props, children }
    }   
    
}

export function render(vdom, container){
    container.appendChild(createDOM(vdom));
}

 

3.virtual DOM

[app.js]
export function render(vdom, container){
    container.appendChild(createDOM(vdom));
}


==> 

export const render = (function(){
    let prevDom = null;

    return function(vdom, container) {
        if(prevDom === null){
            prevDom = vdom;
        }

        //diff

        container.appendChild(createDOM(vdom));
    }
})();

 

 

 

4. 마법의 hook 원리와 제약

[app.js]
/* @jsx createElement */
import { createElement, render, Component } from './react';

class Title extends Component {
    render(){ 
        return <h1>{ this.props.children }</h1>
    }
}
function Item(props){
    return <li style={`color: ${props.color}`}>{props.children}</li>
}
const App = () => <p>
    <Title label="React">React 정말 클래스 컴포넌트 잘 만들기</Title>
    <ul>
        <Item color="red">첫 번째 아이템</Item>
        <Item color="blue">두 번째 아이템</Item>
        <Item color="green">세 번째 아이템</Item>
    </ul>
</p>

render(<App />, document.querySelector('#root'))

console.log(<App />);




[react.js]


const hooks = [];
let currentComponet = 0;

export class Component {
    constructor(props){
        this.props = props;
    }
}

export function createDOM(vdom){
    if(typeof vdom === 'string') {
        return document.createTextNode(vdom);
    }
    const element = document.createElement(vdom.tag);

    Object.entries(vdom.props)
        .forEach(([name, value]) => element.setAttribute(name, value));

    vdom.children
        .map(createDOM)
        .forEach(element.appendChild.bind(element));

    return element;
}
function makeProps(props, children){
    return {
        ...props,
        children: children.length === 1 ? children[0] : children
    }
}

function useState(initValue) {
    let position = currentComponet - 1;

    if(!hooks[position]) {
        hooks[position] = initValue;
    }

    const modifier = nextValue => {
        hooks[position] = nextValue;
    };

    return [ hooks[position], modifier ];
}

export function createElement(tag, props, ...children){
    props = props || {};
    
    if(typeof tag === 'function'){
        if(tag.prototype instanceof Component){
            const instance = new tag(makeProps(props, children))
            return instance.render();
        } 

        hooks[currentComponet] = null;
        currentComponet++;


        if(children.length > 0){
            return tag(makeProps(props, children));
        } else {
            return tag(props);
        }
        
    } else {
        return { tag, props, children }
    }   
    
}

export function render(vdom, container){
    container.appendChild(createDOM(vdom));
}

 

 

 

 


 

[참고사이트]

 

1) awesomeopensource -.virtual DOM

https://awesomeopensource.com/ 

 

2) snabbdom -.virtual DOM

https://github.com/snabbdom/snabbdom

 

3) react hook

https://ko.reactjs.org/docs/hooks-intro.html

 

4) react native

https://reactnative.dev/

 

5) next.js

https://nextjs.org/

 

6) 리액트 어플리케이션 구조 - 아토믹 디자인

https://ui.toast.com/weekly-pick/ko_20200213