[React] 리액트 핵심 원리

mangsuyo·2024년 4월 28일

리액트 철학

A Javascript library for building user interfaces Renders UI and responds to events

UI를 표기하고 event에 반응한다. → UI를 컴포넌트화한다.

한마디로, 리액트는 다른 컴포넌트와 독립적인, 응집력 높은 블락들의 집합체이다.

리액트의 장점

  • 재사용성 [DRY : Don’t Repeat Yourself]
  • 단일책임성 [하나의 컴포넌트에 너무 많은 걸 담지마라]

리액트 동작 원리

리액트는 컴포넌트로 이루어져 있고, 컴포넌트는 State, Props, Render로 구성되어 있다.

State나 Props가 변경되면, 함수가 다시 호출된다.

리액트는 DOM자체를 변경하는 것이 아니라, 메모리 내에서, Virtual DOM(가상요소)의 돔과 상태가 변화하기 전의 DOM과의 차이를 비교하여 차이점만 실제 DOM에 반영한다. <스냅샷과의 비교>

렌더링(함수 호출)이 발생하는 것은 사실이나, 실제 브라우저내에서는 차이점만 업데이트 된다!


리액트 파일 만들기

1) npm 이용
npx create-react-app filename (npx는 npm 2.0 버전 이상에서의 도구이다.)
// 리액트 앱이 설치됨
npm start 
// 웹 서버를 킴

2) npm + vite 
$ npm create vite@latest

React App을 만들기 위해서는 Webpack와 Babel이 필요하다.
일일이 다 설정할 수 없으므로, React에서는 세팅이 완료된 패키지를 제공한다. 이러한 패키지를 Boiler Plate라고 부른다.


보일러 플레이트 안에 있는 것

리액트 기본 패키지에 있는 툴

BABEL : 개발자가 최신 문법을 이용하더라도, older version으로 바꿔준다.

Webpack : 다양한 파일들을 하나로 압축시켜서 번들링해준다.

ESLint : 코드를 잘 작동하고 있는지 확인해준다.

Jest : 테스팅을 할 때 사용하는 라이브러리


JSX 문법 정리

  1. 꼭 닫혀야 하는 태그

    태그는 꼭 닫혀있어야 한다.

  2. 꼭 감싸져야 하는 태그

    두개 이상의 태그는 무조건 하나의 태그로 감싸져있어야 한다.

    <> </> 로 감싸도 괜찮다.

  3. JSX 안에 자바스크립트 문법 사용하기

    JSX 내부에 자바스크립트 문법을 사용 할 때에는 {} 으로 감싸서 보여준다.

    단 선언식이 아닌, 표현식으로만 작성가능하다.

  4. style 과 className

    -로 구분되어 있는 이름들은 camelCase형태로 네이밍 해주어야 한다.

    className은 BEM규칙을 따른다.

    형태[레이아웃] > 의미[무엇을 하는 DOM인지] > 순서_상태를 기본 순서로 사용

  5. 하나의 컴포넌트에는 반시 하나의 root element를 리턴해야 한다.


컴포넌트 스냅샷

처음에 렌더링이 될 때 모든 컴포넌트 함수는 실행을 완료한다.
그 다음 컴포넌트 내에서 이벤트가 발생해도 컴포넌트 함수는 다시 실행되지 않는다.

즉, 변화가 생겼는데도 페이지가 새로 렌더링 되지 않아서 변화가 적용되지 않는다.

어떻게 우리의 의도대로 이벤트 발생 시에 함수를 재호출 할 수 있을까?


Hook : useState

props가 변경되거나, useState가 가지고 있는 값이 변경이 되면, 그것을 포함한 함수를 다시 호출하게 된다.

→ 그렇기 때문에, 가장 최소한의 상태 변경에 대한 책임을 부과해야한다.

useState는, 여러번 호출되어도 리셋되지 않아서 초기값을 기억하고 있다.

setCount에 매개변수로 전달하면, 바로 직전 상태의 값을 변환한다.

// count값은 현재의 코드블럭 밖에서의 count 값이다.
setCount(count + 1); 
// prev, 즉 count는 가장 최신의 count 값이다.
setCount((prev) => prev + 1);

useState의 비밀

useState, 더 정확하게 setState는 비동기적 방식으로 작동한다. 연속적으로 setState가 호출이 되었을 때, 함수는 계속해서 호출이 되어야한다. 이러한 호출은 성능저하로 이어질 수 있고, 때문에 리액트는 성능의 향상을 위해 SetState를 연속 호출하면 배치 처리하여 한 번에 렌더링하더록 하였다.

(배치란 React가 너 나은 성능을 위해 여러개의 state 업데이트를 하나의 리렌더링으로 묶는 것을 의미한다.)


setState(count + 1)
setState(count + 1)
setState(count + 1)
더 자세히 말하자면, count = count + 1 을 반복하고 있다고 생각하면 된다.

동기적 방식으로 하기 위해서는,
setState((prev) => prev + 1);
setState에 함수를 인자로 전달할 때, 동기적 방식으로 useState를 이용할 수 있다.

Props

properties의 줄임말 props, 컴포넌트 간에 데이터 전달이 필요할 때, props를 사용합니다.
props는 기본적으로 객체의 형태이고, 속성들을 객체안에 담고있습니다.

점표기법으로도 접근이 가능하나, 비구조화 할당을 통해 더 쉽게 값을 가져올 수 있습니다.

App.js
<div>
	<Container>
		<Counter/>
		<Hello />
	<Container/>
</div>

// 열린태그와 닫힌 태그 사이에 컨테이너들은 children이라는 props 속성으로 저장된다.
Container.js
Container = ({children}) => {
	...
}
하위 컴포넌트를 상위 컴포넌트 태그로 감싸면, {children}이라는 속성으로
하위 컴포넌트들의 데이터를 받아올 수 있습니다.

React에서 이벤트 핸들링하기

기존 자바스크립트에서 DOM을 특정해서 이벤트를 등록하는 방식이 아닌, Jsx(컴포넌트)내에서 이벤트를 등록합니다.

Ex] onChange = {handleChange}
이벤트가 발생하면 handleChange가 실행됩니다.

import {useState} from 'react'
// 하나의 Input 이벤트 핸들링
// Input은 onChange 이벤트 리스너를 통해 값의 변화 감지
const text = () => {
	const [content, changeContent] = useState('');
	const handleChange = (event) => {
		changeContent(event.target.value);
	}
	return (
		<input onChange = {handleChange}/>
	)
}
// 여러개의 Input 이벤트 핸들링
-> name 이라는 prop을 이용
const text = () => {
	const [state, changeState] = useState({
		author : '',
		content : '',		
	});
	handleChange = (event) => {
		useState({		
			...state,
			[event.target.name]: event.target.value,
		})
	}
--> state 에는 두개의 초깃값이 설정된다.
	<input name = 'author' onChange ={handleChange}/>
	<textarea name = 'content' onChange = {handleChange}/>
}

리스트 렌더링 하기

동적인 배열을 렌더링 해야할 때에는 자바스크립트 배열 내장함수 map()을 사용합니다.

리액트에서 배열을 렌더링 할 때에는 컴포넌트간의 구별을 쉽게 해줄 수 있는 key라는 props를 설정해야 합니다.

DiaryList = (list) => {
	return 
	<div> // jsx내부에서 {}을 이용하여 자바스크립트 문법을 사용할 수 있다.
	{list.map((it) => {
		return <div key = {it.id}>{it.author}</div> // return 안에서도 return jsx가능
		// 배열안의 컴포넌트는 고유한 key값을 가져야 한다.
	}} 
	</div>
}
만약 list를 성공적으로 못받았을 때에는?, props를 못받았을 경우 기본값을 설정할 수 있다.
DiaryList.defaultProps([])

React에서 리스트 삭제하기

리스트에 특정 요소를 삭제하는 방법은 주로 두 가지 방식을 이용합니다.

  • filter이용
    setState(list.filter((item) => item.id !== id)
  • slice이용
    // index를 이용한다.(map에 두번째 인자는 index 임)
    setState([...list.slice(0, index)], [...list.slice(index + 1)]);

 React에서 리스트 수정하기

const onEdit = (targetId, newContent) => {
	setData(data.map((item) => item.id === targetId ? {...item, content: newContent} : item);
}

고유한 Key

React에서 리스트를 반환할 때 각각의 리스트는 고유한 key를 가져야 합니다.

그렇게 해야, key 변화를 기반으로 배열을 원활하게 업데이트 할 수 있습니다.

lists.map((item) => <li key={item.id}>item.title</li>))

 React에서 동적으로 스타일링하기

특정 상황에 따라 스타일이 변경되어야 한다면, 어떻게 해야할까요?

삼항 연산자나 단축평가 등을 이용하여, 동적으로 스타일링 할 수있습니다.

className이 하나 일 때
<div className={isCheck ? 'list__checkText' : 'list__text}>

className 두개 이상일  (리터럴 방식과 함께 사용)
<div className={`form-control ${!isValid ? 'invalid' : ''}`}>

또한 표현식인 단축평가 등을 이용하여, 조건에 따라 동적 스타일링 할 수 있다.
<div className={{props.name === "" && 'isTrue'}}>

profile
한망수요

0개의 댓글