React

Yongjun Park·2022년 9월 15일
0

2022 OSAM 해커톤

목록 보기
7/11

2022 OSAM 해커톤 사전 온라인 교육에서 배운 내용입니다.
모르는 내용만 발췌하여 정리한 것이기 때문에 내용의 연결성이 부족한 점 양해 부탁드립니다.

사전지식

1. TypeScript

TypeScript 한글 문서

2. React.createElement & JSX

React스럽게 리팩토링하기 : 노마드코더 ReactJS 초반부 정리

React 프로젝트 환경 구성

Adding TypeScript | Create React App

수작업으로 한다면?

설정 파일 빠르게 작성하고, 설치 수작업으로 했는데 한번에 잘 작동되는게 너무 멋있다

Concepts | 웹팩

  • webpack : tsx→jsx→js로 바꿔주는 기능
  • webpack dev-server : js 파일을 서버로 띄워서 바로 웹페이지를 확인할 수 있게 하는 기능

Diffing Algorithm

재조정 (Reconciliation) - React

엘리먼트의 타입이 다른 경우

이전 트리를 버리고 완전히 새로운 트리를 구축한다.

ex) <a>에서 <img>로, <Article>에서 <Comment>로, 혹은 <Button>에서 <div>로 바뀌는 것 모두 트리 전체를 재구축하는 경우

<div>
	<Counter />
</div>

<span>
	<Counter />
</span>

이전 Counter는 사라지고, 새로 다시 마운트가 될 것입니다.

DOM 엘리먼트의 타입이 같은 경우

동일한 내역은 유지하고 변경된 속성들만 갱신합니다. 예를 들어,

<div className="before" title="stuff" />

<div className="after" title="stuff" />

이 두 엘리먼트를 비교하면, React는 현재 DOM 노드 상에 className만 수정한다.

style이 갱신될 때, React는 또한 변경된 속성만을 갱신한다. 예를 들어,

<div style={{color: 'red', fontWeight: 'bold'}} />

<div style={{color: 'green', fontWeight: 'bold'}} />

위 두 엘리먼트 사이에서 변경될 때, React는 fontWeight는 수정하지 않고 color 속성 만을 수정한다.

DOM 노드의 처리가 끝나면, React는 이어서 해당 노드의 자식들을 재귀적으로 처리한다.

같은 타입의 컴포넌트 엘리먼트

렌더링 간 state는 유지되며, props는 갱신된다.

자식에 대한 재귀적 처리

기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성합니다. 예를 들어,

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React는 두 트리에서 <li>first</li>가 일치하는 것을 확인하고, <li>second</li>가 일치하는 것을 확인한다. 그리고 마지막으로 <li>third</li>를 트리에 추가한다.

하지만 위와 같이 단순하게 구현하면, 리스트의 맨 앞에 엘리먼트를 추가하는 경우 성능이 좋지 않다. 하나만 바꾸면 되는데 통째로 다 바꿔야하기 때문이다.

Keys

이러한 문제를 해결하기 위해, React는 key 속성을 지원한다. key는 다음과 같이 생성된다.

  1. id 속성이 있다면, 그 id를 key로 활용한다.
  2. id가 없다면, 데이터 일부에 해시를 적용해서 만든다. 해당 key는 오로지 형제 사이에서만 유일하면 되고, 전역에서 유일할 필요는 없으니까.
  3. 데이터도 같다면, 최후의 수단으로 배열의 인덱스를 key로 사용할 수 있다. 항목들이 재배열되지 않는다면 이 방법도 잘 동작할 것이지만, 재배열되는 경우 비효율적으로 동작할 것.

클래스형 컴포넌트

클래스형 컴포넌트와 함수형 컴포넌트

  • 예전의 React에서는, 함수형 컴포넌트에 제약이 있었다.
    • 함수형 컴포넌트는 state를 가질 수 없다.
    • 함수형 컴포넌트는 생명 주기 함수(constructor, render 등)를 사용할 수 없다.
  • 하지만, 훅(Hook)이 등장하면서 함수형 컴포넌트에서도 state와 생명 주기 함수를 작성할 수 있게 되었으며 이젠 클래스형 컴포넌트를 쓸 이유가 없게 되었다.

props & state 활용 예제

// Counter.tsx

import * as React from "react";

interface CounterProps {
	title: string;
}

interface CounterState {
	num: number;
}

class Counter extends React.Component<CounterProps, CounterState> {
	constructor(props: CounterProps) {
		super(props);

		// state를 만드는 법. 무조건 constructor에서만 가능
		this.state = {
			num: 0,
		}
	}

	handleClick = () => {
		this.setState((prev => {
			return {
			num: prev.num + 1,
			};
		});
	};

	render() {
		return (
			<div>
				<h1>{this.props.title}</title>
				<h3>Count: {this.state.num}</h3>
				<button onClick={this.handleClick}>Plus</button>
			</div>
		);
	}
}

export default Counter;
// index.tsx

import * as React from "react";
import { createRoot } from "react-dom/client";
import Counter from "./Counter";

const rootNode = document.getElementById("root");
const reactRoot = createRoot(rootNode!);

reactRoot.render(<Counter title="이건 Counter야" />);

Hooks

  • 컴포넌트 외부로 렌더 로직을 분리하기 위한 수단으로, 로직의 재사용성을 높인다는 장점이 있다. View는 함수형 컴포넌트에서, Logic은 Hook에서 담당.
    • 따라서 함수형 컴포넌트에서는, State와 Life Cycle 함수를 직접 관리하지 말아야 한다.

Counter.tsx 함수형 컴포넌트로 마이그레이션

// Counter.tsx

import * as React from "react";

interface CounterProps {
	title: string;
}

function Counter(props: CounterProps): React.ReactElement {
	const [count, setCount] = React.useState(0);
	const add = () => setCount((prev) => prev+1);
	return (
		<div>
			<h1>{props.title}</title>
			<h3>Count: {count}</h3>
			<button onClick={add}>Plus</button>
		</div>
	);
}

export default Counter;

**Counter를 arrow function으로 만들어보자!**

// Counter.tsx

import * as React from "react";

interface CounterProps {
	title: string;
}

const Counter: React.FC<CounterProps> = ({title}) => {
	const [count, setCount] = React.useState(0);
	const add = () => setCount((prev) => prev+1);
	return (
		<div>
			<h1>{title}</title>
			<h3>Count: {count}</h3>
			<button onClick={add}>Plus</button>
		</div>
	);
};

export default Counter;

Logic을 완전히 분리해보자!

count 말고 다른 state가 생겨도 Counter 함수 안에서 만들텐데, 함수형 컴포넌트에서는 굳이 여러가지 state가 한 컴포넌트 안에 존재할 필요 없음.

// Counter.tsx 수정된 부분만
import { useCounter } from "./hooks/useCounter";

//	const [count, setCount] = React.useState(0);
	const { count, add } = useCounter();

// hooks/useCounter.ts
import * as React from "react";

interface UseCounterReturnType {
	count: number;
	add: () => void;
}

function useCounter(): UseCounterReturnType {
	const [count, setCount] = React.useState(0);

	const add = () => setCount((prev) => prev+1);

	return {
		count,
		add
	};
}

useMemo & useCallback

업로드중..

[React] useCallback과 useMemo 제대로 사용하기

profile
추상화되었던 기술을 밑단까지 이해했을 때의 쾌감을 잊지 못합니다

0개의 댓글