본문 바로가기
제니의 개발일지/개발일지

항해99 4주차 WIL - 라이프사이클(클래스형 vs 함수형), react hooks

by 제니운 2022. 8. 8.
728x90

 

 

벌써 4주차 WIL 이다.

4주차는 사실 그렇게까지 힘들진 않았다. 팀원들과의 협업도 잘 되고 팀원들과 성격도 잘 맞고 대화도 잘 되서 하루하루 힘들지만 행복하게 시간을 보냈다. 그런데 4~5주차 넘어가는 지금이 조금 힘들다.

5주차 WIL이 약간 걱정되는 밤이다. 너무 힘들어서 어제는 눈물이 났다. 눈물이 거의 없는 편인데도 서러운 부분이 있었다.

어쨌든,,, 잘 극복하고 이번 한주를 보내길 바라며 지난주 WIL을 작성해본다!

 

 

🤗 좋았던 것은!

 

리액트 기초반 강의 완강, 입문+숙련 학습자료 완독 및 블로그 정리 완료, 자바스크립트 하루 목표 완료! 모두 목표했던 일정을 완료하였다.

 

 

🕶️ 아쉬웠던 것은!

 

CS 책을 이틀이나 누락했다. 스터디 발표 공유하는 날에는 열심히 준비했는데 앞뒤로 사실 챕터를 읽지 못했다. 10분만이라도 투자해서 읽으면 되는 것을, 무엇이 그렇게 싫었는지 책에 손이 가지 않았다. 그러다 보니 맥락 이해도 조금 떨어졌다. 사실 CS책을 보고 있으면 지금 막 이해가 되는 것은 없다. 그렇지만 꾸준히 읽고 반복하다 보면 이해가 되겠지, 전공 지식이 넓어지겠지 라는 마음으로 꾸준히 하고 있었는데 확실히 프로젝트를 시작하면서 아주 조금은 내가 지쳐가고 있나보다. 책 읽는 것을 정말 좋아하는 내가 책에 손이 가지 않고 있다는 것은 정체성이 무너지는 느낌(?)

 

그리고 개인적으로 힘든 일을 내가 자꾸 상기하고 있다. 그 일을 상기해서 좋을 것이 없는데, 하루 종일 공부하고 프로젝트할때는 괜찮은데 자꾸 밤만 되면 센치해지는 건지 안 좋은 생각이 계속 들고 있다. 그럴떄마다 산책을 나가고 있는데, 산책을 하면 덥고 더우니까 들어와서 씻고 자리에 앉고 이 과정을 반복중이다.ㅎㅎ...

 

시간이 모든 것을 해결해줄 것이기 때문에, 시간이 해결해주는 동안 최선을 다해보자! 지금 힘든 5주차 ㅠㅠ 겪어 내자 !

 

 

 

✅ 4주차 WIL 복습 내용

 

1️⃣ 라이프사이클

 

라이프사이클은 기초반 강의 자료 정리를 하면서 블로그에 기재해둔 내용이다. 강의 자료를 보면서 다시한번 복습하기

 

▶️ 컴포넌트는 생성되고 -> 수정(업데이트)되고 -> 사라진다.

▶️ 생성은 처음으로 컴포넌트를 불러오는 단계이다.

▶️ 수정(업데이트)는 사용자의 행동(클릭, 데이터 입력 등)으로 데이터가 바뀌거나, 부모 컴포넌트가 렌더링할 때 업데이트 된다.

 

- props가 바뀔 때

- state가 바뀔 때

- 부모 컴포넌트가 업데이트 되었을 때(=리렌더링했을 때)

- 또는, 강제로 업데이트 했을 경우!(forceUpdate()를 통해 강제로 컴포넌트를 업데이트할 수 있다)

 

▶️ 제거는 페이지를 이동하거나, 사용자의 행동(삭제 버튼 클릭 등)으로 인해 컴포넌트가 화면에서 사라지는 단계이다.

 

 

👌 constructor()

 

생성자 함수라고도 부른다. 컴포넌트가 생성되면 가장 처음 호출되는 것

 

 

👌 render()

 

컴포넌트의 모양을 정의하는 것

여기서도 state, props에 접근해서 데이터를 보여줄 수 있다.

리액트 요소를 return에 넣어 반환해줬는데, render()안에 들어갈 내용은 컴포넌트의 모양에만 관여하는 것이 가장 좋다. 즉, state나 props를 건드려 데이터를 수정하려고 하면 안된다.

 

 

👌 componentDidMount()

 

컴포넌트가 화면에 나타나는 것을 마운트한다고 표현한다. DidMount()는 마운트가 완료되었다는 소리이다.

이 함수는 첫번째 렌더링을 마친 후에만 딱 한번 실행된다. 컴포넌트가 리렌더링할때는 실행되지 않는다. 보통은 이 안에서 ajax 요청, 이벤트 등록, 함수 호출 등 작업을 처리한다. 이미 가상돔이 실제돔으로 올라간 후이므로 DOM 관련 처리를 해도 된다.

 

 

👌 componentDidUpdate(prevProps, prevState, snapshot)

 

DidMount()가 첫 렌더링 후에 호출되는 함수라면, DidUpdate()는 리렌더링을 완료한 후 실행되는 함수이다.

 

이 함수에 중요한 파라미터가 2개 있는데, prevProps와 prevState이다. 각각 업데이트 되기 전 props, state 이다. 이전 데이터와 비교할 일이 있다면 가져다 쓰면 된다. DidUpdate()가 실행될 때도 가상돔이 실제돔으로 올라간 후니까 DOM관련 처리를 해도 된다.

 

 

👌 componentWillUnmount()

 

컴포넌트가 DOM에서 제거 될 때 실행하는 함수이다. 스크롤 위치를 추적 중이거나, 어떤 이벤트 리스너를 등록했다면 컴포넌트 없이 이벤트만 남겨둘 수 없으므로, 여기서 꼭 해제를 해줘야 한다. 

 

import React from "react";

// 클래스형 컴포넌트는 이렇게 생겼다.
class LifecycleEx extends React.Component{
	
    //생성자 함수
    constructor(props){
    	super(props);
        
        this.state = {
        	cat_name = "나비",
        }
        console.log("in constructor!");
    }
    
    changeCatName = () => {
    	// state 업데이트 하는 방법이다.
    	this.state({cat_name: "바둑이"});
        console.log("고양이 이름을 바꾼다!")
    }
    
    componentDidMount(){
    	console.log("in componentDidMount")
    }
    
    componentDidUpdate(prevProps, prevState){
    	console.log(prevProps, prevState);
        console.log("in componentDidUpdate")
    }
    
    componentWillUnmount(){
    	console.log("in componentWillUnmount!)
    }
    
    // 렌더 함수 안에 리액트 엘리먼트 넣어주기
    render(){
    	console.log("in render!");
        
        return(
        	<div>
            	<h1>제 고양이 이름은 {this.state.cat_name}입니다.</h1>
                <button onClick={this.changeCatName}>고양이 이름 바꾸기</button>
            </div>
        )      
    }
}

export default LifecycleEx;

 

 

2️⃣ react hooks

 

React 숙련 학습 자료 정리를 하면서 기재한 내용이지만, 다시 한번 공부하고 노션 자료를 되새기는 마음으로 WIL 쓰는 김에 또 작성해보고자 한다.

 

 

👌 useState

 

useState는 가장 기본적인 hook 이며, 함수 컴포넌트에서 가변적인 상태를 가지게 해준다.

 

const [state, setState] = useState(initialState);

 

state를 변수로 사용했고 setState를 이용해서 state값을 수정할 수 있었다. 만약, state가 원시 데이터타입이 아닌 객체 데이터 타입인 경우에는 불변성을 유지해줘야 한다.

 

 

🔹 함수형 업데이트

 

setState를 사용하는 방식에는 함수형 업데이트 방식이 있다.

 

 

// 기존에 사용하던 방식
setState(number +1);

// 함수형 업데이트
setState(() => {});

 

 

setState () 안에 수정할 값이 아니라 함수를 넣을 수 있다. 그리고 그 함수의 인자에서는 현재의 state 값을 가져올 수 있고 {}안에서는 이 값을 변경할 수 있는 코드를 작성할 수 있다.

 

 

// 현재 number의 값을 가져와서 그 값에 1를 더하여 반환한 것
setState((currentNumber) => {
	retrun currentNumber + 1
})

 

 

▶️ 두 방식의 차이점

 

 

<button
	onClick={() => {
    	setNumber(Number + 1);
        setNumber(Number + 1);
        setNumber(Number + 1);
    }}
>
버튼
</button>

 

 

이렇게 일반 업데이트 방식으로 setNumber(number + 1)을 3번 호출하면, number 가 1씩 증가한다.

 

 

<button
	onClick = {() => {
    	setNumber((previousState) => previousState + 1 );
        setNumber((previousState) => previousState + 1 );
        setNumber((previousState) => previousState + 1 );
    }}
>버튼</button>

 

 

함수형 업데이트 방식으로 동일하게 작동시키면 number가 3씩 증가한다.

 

일반 업데이트 방식은 버튼을 클릭했을 때 첫번째 줄~세번째 줄에 있는 setNumber가 각각 실행되는 것이 아니라, 배치(batch)로 처리한다. 즉, onClick했을 때 setNumber라는 명령을 세번 내리지만, 리액트는 그 명령을 하나로 모아 최종적으로 한번만 실행시킨다. 그래서 setNumber를 3번 명령하던, 100번 명령하던 1번만 실행된다.

 

반면, 함수형 업데이트 방식은 3번을 동시에 명령을 내리면 그 명령을 모아 순차적으로 각각 1번씩 싱행시킨다. 그래서 최종적으로 3이라는 결과가 눈에 보인다.

 

 

👌 useEffect

 

useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 hook이다. 어떤 컴포넌트가 화면에 보여졌을 때 내가 무언가를 실행하고 싶다면, 또는 어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면 useEffect를 사용한다.

 

useState와 마찬가지로 React에서 제공하는 훅(기능)이므로, import {useEffect} from "react"로 import 해서 사용한다.

 

 

import React, {useEffect} from "react";

const App = () => {
	useEffect(() => {
    	// 이 부분이 실행된다.
        console.log("hello useEffect");
    })
    
    return <div>Home</div>
}

export default App;

 

 

브라우저에서 App 컴포넌트를 눈으로 보는 순간, 즉 App 컴포넌트가 화면에 렌더링될 때 useEffect 안에 있는 console.log가 실행된다. 컴포넌트가 렌더링 될 때 실행되는 것, useEffect 핵심 기능이다.

 

 

🔹 useEffect와 리렌더링(re-rendering)

 

useEffect가 속한 컴포넌트가 화면에 렌더링 될 때 실행되는 특징에 의해 의도치 않은 동작을 경험할 수도 있다.

 

import React, {useEffect} from "react";

const App = () => {
	const [value, setValue] = useState("");
    
    useEffect(() => {
    	console.log("hello useEffect")
    })
    
    return(
    	<div>
        	<input
            	type = "text"
                value = {value}
                onChagne = {(event) => {
                	setValue(event.target.value)
                }}
            />
        </div>
    )
}

export default App;

 

 

input이 있고 value 라는 state 를 생성하여 input 과 연결시켰다. 이렇게 구현하고 브라우저에서 input에 어떤 값을 입력하면 useEffect가 계속 실행되는 것을 볼 수 있다.

 

state가 변경되었기 때문에 App 컴포넌트가 리렌더링 되었고 리렌더링 되었기 때문에 useEffect가 다시 실행되어 계속 순환된 것. 

 

 

🔹 의존성 배열 

 

import React, {useEffect} from "react";

const App = () => {
	const [value, setValue] = useState("");
    
    useEffect(() => {
    	console.log("hello useEffect")
    }, [])
    
    return(
    	<div>
        	<input
            	type = "text"
                value = {value}
                onChagne = {(event) => {
                	setValue(event.target.value)
                }}
            />
        </div>
    )
}

export default App;

 

useEffect (() => {}, [의존성 배열])

 

 

▶️ 의존성 배열이 빈 배열인 경우

 

이 배열 에 값이 바뀔 때만 useEffect를 실행할게라는 의미이므로, 아무것도 넣지 않았으니 useEffect는 딱 한번만 실행되고 어떤일이 일어나도 실행이 되서는 안된다.

 

 

▶️ 의존성 배열에 값이 있는 경우

 

useEffect(() => {}, [value])

 

value는 state이고 input을 입력할 때마다 그 값이 변하게 되니 useEffect도 계속 실행이 된다.

 

 

🔹 clean up

 

어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면 ! 이 과정을 클린 업이라고 표현한다.

 

 

▶️ 클린 업 하는 방법

 

import React, {useEffect} from "react";

const App = () => {
	useEffect(() => {
    	//화면에 컴포넌트가 나타났을 때(mount) 실행하고자 하는 함수 넣기
    	return() => {
        	// 화면에서 컴포넌트가 사라졌을(unmount)때 실행하고자 함수 넣기
        }
    },[])
    
    return <div>hello react!</div>
}

export default App;

 

useEffect 안에서 return을 해주고 이 부분에서 실행되길 원하는 함수를 넣으면 된다.

728x90