React 기초공부-2

솔다·2023년 2월 7일
0

Element란?

리액트 앱을 구성하는 가장 작은 블록들을 말합니다. Virtual DOM에 존재하는 Element를 말하며, 화면에 표시되는 자바스크립트 내용들을 담고 있다. (DOM Element는 우리가 화면에서 볼때의 Element를 말한다.)

코드 내에서는 일반적으로 자바스크립트 객체 형태로 존재하고, 한번 작성되면 수정될 수 없다는 특징이 있습니다.(Immutable) 정확히는 한번 element로 생성된 후에는 수정이 불가능하다는 점.

수정을 위해서는 새롭게 렌더링을 다시해주는 것 밖에없다.

위의 코드를 보면 tick 마다 새롭게 호출해서 만들고 있다. 이미 만들어진 element의 수정을 위해서는 그냥 새롭게 만들어서 다시 렌더링 해주는 방법 밖에는 없다.

Root DOM Node

리액트로 만들어진 페이지는 아래의 그림처럼 하나의 루트돔을 가진다.

기존에 만들어진 페이지에 리액트를 연동한 경우 여러개의 루트돔을 가질 수 도 있다.

Componenets와 Props

  • React Component: props를 넣어주면 리액트 Element를 생성해준다. 객체지향에서 오는 특성이다.
  • Prop: Property의 줄임말이다. props는 react element를 생성하기 위해 사용하는 값이다. props의 값은 이미 생성된 뒤에는 수정할 수 없다.

=> 모든 리액트 컴포넌트는 Props를 직접 바꿀 수 없고, 같은 Props에 대해서는 항상 같은 결과(React Element)를 보여주어야 한다.

Props 사용방법

function App(props){
	return(
    	<Profile
        	name = "sol"
            introduction = "안녕하세요."
            viewCount = {1500}
        />
    );
}

위의 코드처럼 키와 값의 쌍의 형태로 넣을 수 있다. 위에 작성된 코드에서 props 마다 차이점이 있는데 중괄호{} 를 사용한 경우, 앞에서 JSX에서는 자바스크립트 코드가 들어간다고 배웠는데, 문자열 이외에 정수/변수/다른 컴퍼넌트 를 작성할때는 {}안에다가 넣어주어야 한다.


위의 그림처럼 작성하면 header에 새로운 컴포넌트가 들어간게도 구성할 수 있다.

React Componenet 만들기

Component는 Function Componenet와 Class Component 로 나뉘어 진다.

Function Componenet

function Welcome(props){
	return <h1>안녕, {props.name}<h1>
}

위의 코드를 보면 함수가 굉장히 간단하고 element를 반환하는 녀석이다. 매우 간단하다는 장점이 있다.

이번에는 위와 동일한 것을 수행하는 Class Component를 만들어보자

class Welcome extends React.Component {
	render(){
    	return <h1>안녕, {this.props.name}</h1>;
    }
}

함수 컴포넌트와의 가장 큰 차이점은 리액트의 모든 클래스 컴포넌트는 React.Component를 상속받아서 만든다.

Component의 이름은 항상 대문자로 시작해야 한다!

소문자로 시작하는 Component를 DOM 태그로 인식하기 때문이다.

Component 렌더링

아래 코드로 예시를 직접 보자.

function Welcome(props) {
	return <h1>안녕, {props.name}</h1>;
}

const element = <Welcome nam="인제" />; //Welcome이라는 함수 Component에 "인제" 라는 props 값 대입
ReactDOM.render( //실제로 렌더링 되는 부분
	element,
    document.getElementById('root')
);

위 함수에서 보면 function component로 생성한 뒤에, ReactDOM.render()로 렌더링 해주는 것을 볼 수 있다.

Component 합성

React에서는 Component 안에 Component를 넣어줄 수 있기 때문에, 여러개의 Component를 조합해서(=합성해서) 만들어줄 수 있으며, 매우 쉽게 작성할 수 있다. 아래의 예시를 보자.

이 Component의 Props는 아래와 같을 것입니다.

이제 이 Component를 추출해서 만들어봅시다. 먼저 아바타를 추출해봅시다.

<img className="Avatar"> //이 태그 부분을 함수 Componenet로 만들면 아래와 같다.

function Avatar(props){
	retunr(
    	<img className="avatar"
        	src={props.user.avatarUrl}
            alt={props.user.name}
        />
    );
}

이렇게 추출한 Component를 적용하면 아래의 그림과 같이 된다.

붉은 색 네모칸 안에는 UserInfo를 담고 있다. 이 부분을 또 새롭게 Componenet로 만들면 다음과 같다.

이제 이 부분을 추출하고 반영하면

이렇게 코드가 매우 간단하게 나타낼 수 있음을 알 수 있다. 이런식으로 재사용 가능한 Component를 많이 가지고 있을 수록 개발 속도가 많이 증가하게 된다.

React에서의 State와 Lifecycle

React에서의 State는 React Component의 변경 가능한 데이터를 통상적으로 말한다. 개발자가 이 state를 정의해야 하는데, 렌더링이나 데이터 흐름에 사용되는 값만 state에 포함시켜야 한다.

state는 일반적인 자바스크립트 객체이다.(Class Component에서 사용함)

위의 코드는 class component를 생성하는 코드이다. 여기서 state를 수정하고 싶다면 어떻게 해야 할까? 아래의 작성된 코드를 보자.

//state를 직접 수정(잘못된 사용법)
this.state = {
	name: 'Inje'
};

//
this.setState({
	name: 'Inje'
});

위의 두 경우를 보면, State를 수정하는 코드인데, state는 직접 수정이 가능하기는 하지만, setState()를 이용해서 수정해야 한다. 그래야 렌더링시에 개발자가 의도한 바를 벗어나지 않고 옳게 수행된다.

HOOKS

HOOK 이란?
갈고리라는 뜻인데, 말그대로 state관련함수/lifecycle 관련 함수/최적화 관련함수 들에 갈고리를 걸어서 function component에서도 class에서 사용하던 기능들을 사용할 수 있는 것이다.

import React, { useState } from "react";
function Counter(props) {
	var count = 0;
    
    return (
    	<div>
        	<p>총 {count}번 클릭했습니다.</p>
            <button onClick={() => count++}>
            	클릭
            </button>
        </div>
    );
}

위 함수를 보면, 버튼을 클릭할때마다 count가 계속 증가는 하지만, 변경된 값을 따라서 화면이 재랜더링이 되지 않아서 표시되지 않는다.

그래서 useState()를 호출해서 랜더링되도록 한다.

const[변수명, set함수명] = useState(초기값);

위와 같이 사용하는데, 위쪽의 예시에 실제로 적용해보자.

import React, { useState } from "react";
function Counter(props) {
	const [count, setCount] = useState(0);
    
    return (
    	<div>
        	<p>총 {count}번 클릭했습니다.</p>
            <button onClick={() => count++}>
            	클릭
            </button>
        </div>
    );
}

위의 경우를 보면, count값을 useState()를 이용해서 state로 만들어 관리화도록 만든 것이다. state변수를 count라는 이름으로, setState()함수를 setCount()라는 이름의 함수로 되어있는 것을 확인가능하다.

onClick이벤트에 setCount()를 사용해서 count값을 변경해주고 랜더링이 다시 일어나게 한다.

Side Effect

Side Effect란? 일반적으로는 부정적인 의미이지만, 자바스크립트에서는 그렇게 부정적으로 사용하지는 않는다. 일반적인 효과/영향의 의미로 사용된다. 예를들어 서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 작업등을 effect라고 하는데, 이런 것들은 다른 컴포넌트에 영향을 끼칠 수 있으며, 렌더링 중에는 실행이 불가능하다.

useEffect(이펙트함수, 의존성 배열);
위와 같은 방식으로 작성하는데,
// 컴포넌트가 마운트 된 이후,
// 이 배열 안의 값이 하나라도 변경되면 그때마다 useEffect() 실행
// 배열에 빈 배열을 넣으면, mount,unmount 시에 단 한 번씩만 실행됨.
//배열을 그냥 생력해버리면, component 업데이트시마다 수행 됨.

아래 예제를 보자

import React, { useState } from "react";
function Counter(props) {
	const [count, setCount] = useState(0);
    
    useEffect(()=> {
    	document.title = `You clicked ${count} times`;
    });
    return (
    //컴포넌트가 마운트 해제되기 전에 실행됨
    	<div>
        	<p>총 {count}번 클릭했습니다.</p>
            <button onClick={() => count++}>
            	클릭
            </button>
        </div>
    );
}

useMemo

useMemo()란, 연산이 많이 드는 함수 호출 결과를 여러번 하기보다는 함수 호출 결과를 보관했다가(Momoized Value) 바로 호출하는 방식으로 컴퓨터 자원을 적게 사용할 수 있다.

const memoizedValue = useMemo(
	()=> {
    	return comnputeExpensiveValue(의존성 변수1, 의존성 변수2);
       },
       [의존성 변수1, 의존성 변수2]
);

useMemo()의 경우에는 렌더링중에 실행되므로 sideEffect()같은 훅은 여기에 같이 걸어서는 안된다.

주의할 점이 몇가지 있다.
//의존성 배열이 빈 배열인 경우, 컴포넌트 마운트 시에만 호출됨
//의존성 배열을 아예 안 넣는 경우, 컴포넌트가 렌더링 될 때마다 호출됨

useCallback

useMemo() 굉장히 비슷한데, 함수를 반환해준다. 컴포넌트가 렌더링 되면서 값이 변경된 경우에만 callback()함수를 반환한다.

const memoizedCallback = useCallback(
	() => {
    	doSomething(의존성 변수1, 의존성 변수2);
    },
    [의존성 변수1, 의존성 변수2]
);

위와같이 사용함. 의존성 변수 중 한개라도 변경되면 의존성 변수를 반환한다.

useRef

reference를 쓰기위한 훅이다. 리액트에서 레버런스란, 특정 컴포넌트에 접근할 수 있는 객체를 말하며, useRef는 그런 객체를 반환한다.

reference로 반환된 오브젝트인
refObject에는 refObject.current 라는 속성이 있는데, 이는 현재 참고하고 있은 레퍼런스를 의미한다.

사용방법은 아래와 같다.

const refContainer = useRef(초기값);

만일 초기값이 null이라면 초기값이 null인 객체가 반환된다. 즉, 컴포넌트가 마운트 해제 될때까지는 값이 유지된다.

//다양한 변수를 저장할 수 있다는 장점이 있다.
//내부의 데이터가 변경되었을 때 별도로 알리지 않는다.
//내부 데이터 변경에 따른 조치를 하고 싶으면, useCallback()을 사용하자

Hook의 규칙

//Hook은 무조건 최상위 레벨에서만 호출해야 한다. if, for문이나 while문 등 내부에서 실행하면 안된다.
//리액트 함수 컴포넌트 내부에서만 Hook을 호출해야 한다. 일반적인 자바스크립트에서는 호출하면 안된다.

Custom Hook 만들기

Custom Hook을 만들어야 하는 상황은?

중복되는 로직을 하나로 하고 싶은 경우

이름이 use로 시작하고, 내부에서 다른 hook을 호출하는 하나의 자바스크립트 함수가 Custom Hook이다.

custom훅은 단순한 함수와 같고 인수로 받을게 무었일지 전부 개발자가 결정한다. 그래서 필요한 것들을 넣을 수 있으며, hook답게 규칙이 적용된다.

0개의 댓글