WEB/react

State and LifeCycle(생명주기)

일상코더 2023. 3. 7. 01:45

element 렌더링을 이용한 째깍거리는 시계 예시

 

const root = ReactDOM.createRoot(document.getElementById('root'));

function tick(){
	const element = (
    	<div>
            <h1>Hello, world</h1>
            <h1>It is {new Date().toLocaleTimeString()}.</h1>
        </div>
    );
    root.render(element);
}

setInterval(tick, 1000);

 

Clock 컴포넌트를 만들어서 완전히 재사용 하고 캡슐화 하는 방법

const root = ReactDOM.createRoot(document.getElementById('root'));

function Clock(props){
	return(
    	<div>
        	<h1>Hello, world!</h1>
           	<h1>It is {props.date.toLocaleTimeString()}.</h1>
        </div>
    );
}

function tick(){
	root.render(<Clock date={new Date()} />);
}

setInterval(tick, 1000);

-> 중요한 요건이 누락 되어있다.

-> Clock 이 타이머를 설정하고 매초 UI를 업데이트 하는 것이 빠짐

 

 

이상적으로 한 번만 코드를 작성하고 Clock이 스스로 업데이트 하도록 만들기

-> 이것을 구현하기 위해 State개념을 추가 해야 한다. 

-> state 는 props와 유사하지만, 비공개이며 컴포넌트에 의해 완전히 제어된다.

 

 

함수에 클래스로 변환하기

 

              1. React.Component를 확장하는 동일한 이름의 ES6 class를 생성한다. 

              2. render() 라고 불리는 빈 메서드를 추가한다. 

              3. 함수의 내용을 render() 메서드 안으로 옮긴다. 

              4. render() 내용 안에 있는 props 를 this.props로 변경한다. 

              5. 남아있는 빈 함수 선언을 삭제한다. 

class Clock extends React.Component{
    render(){
    	return(
        	<div>
            	<h1>Hello, world!</h1>
                <h1>It is {this.props.date.toLocaleTimeString()}.</h1>
            </div>
        );
    }
}

-> Clock 은 이제 함수가 아닌 클래스로 정의된다. 

-> render 메서드는 업데이트가 발생할 때마다 호출되지만, 같은 DOM 노드로 <Clock/>을 렌더링하는

     경우 Clock 클래스의 단일 인스턴스만 사용된다. 이것은 로컬 state 생명주기 메서드와 같은 

     부가적인 기능을 사용할 수 있게 해준다

 

 

클래스에 로컬 State 추가하기

 

       1. render() 메서드 안에 있는 this.props.date 를 this.state.date로 변경한다. 

 

class Clock extends React.Component{
	render(){
    	return(
        	<div>
            	<h1>Hello, world!</h1>
                <h1>It is {this.state.date.toLocaleTimeString()}.</h1>
            </div>
        );
    }
}

   

      2. this.state를 지정하는 class constructor를 추가한다. 

class Clock extends React.Component{
	constructor(props){
    	super(props);
        this.state = {date: new Date()};
    }
    
    render(){
    	return(
        	<div>
            	<h1>Hello, world!</h1>
                <h1>It is {this.state.date.toLocaleTimeString()}.</h1>
            </div>
        );
    }
}

    * 클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 한다.

 

생명주기 메서드를 클래스에 추가하기

 

class Clock extends React.Component{
	constructor(props){
    	super(props);
        this.state = {date: new Date()};
    }
    //컴포넌트 출력물이 DOM에 렌더링 된 후에 실행 된다. 
    //-> 타이머를 설정하기 좋은 장소
    componentDidMount(){
    	this.timerID = setInterval(
        	() => this.tick(), 1000
        );
    }
    
	componentWillUnmount(){
    	clearInterval(this.timerID);
    }
    
    tick(){
    	this.setState({
        	date: new Date()
        });
    }
    render(){
    	return (
        	<div>
            	<h1>Hello, world!</h1>
                <h1>It is {this.state.date.toLocaleTimeString()}.</h1>
            </div>
        );
    }
}

const rood = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);

-> <Clock />가 root.render() 로 전달 되었을 때 React는 Clock 컴포넌트의 constructor를 호출한다. 

-> Clock이 현재 시각을 표시해야 하기 때문에 현재 시각이 포함된 객체로 this.state를 초기화 한다. 

-> 나중에 이 state를 업데이트 한다. 

-> React는 Clock 컴포넌트의 render() 메서드를 호출한다. 

-> 이를 통해 React는 화면에 표시되어야 할 내용을 알게 된다.

-> React는 Clock의 렌더링 출력값을 일치 시키기 위해 DOM을 업데이트 한다. 

-> Clock 출력값이 DOM에 삽입되면, React는 componentDidMount() 생명주기 메서드를 호출 한다.

-> 그 안에서 Clock 컴포넌트는 매초 컴포넌트의 tick() 메서드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청

-> 매초 브라우저가 tick() 메서드를 호출한다. 그안에서 Clock 컴포넌트는 setState()에 현재 시각을 포함하는 

     객체를 호출하면서 UI업데이트를 진행한다. 

-> setState() 호출 덕분에 React는 state가 변경된 것을 인지하고 화면에 표시될 내용을 알아내기 위해 render()

     메서드를 다시 호출한다. 

-> 이 때 render() 메서드 안의 this.state.date가 달라지고 렌더링 출력값은 업데이트된 시각을 포함한다. 

-> React는 이에 따라 DOM을 업데이트 한다. 

-> Clock 컴포넌트가 DOM으로부터 한 번이라도 삭제된 적이 있다면 React는 타이머를 멈추기 위해 

     componentWillUnmount() 생명주기 메서드를 호출한다.