Ian's Archive 🏃🏻

thumbnail
React 핵심 기능
React
2022.08.15.

이번 포스팅에서는 리액트의 핵심원리에 대해 정리!!


리액트는 사용자 인터페이스를 구축하는 자바스크립트 라이브러리

왜 리액트를 사용하는가

Javascript는 브라우저 내 DOM조작, 이를 통해 화면을 랜더링한다.

리액트는 컴포넌트 기반의 UI 라이브러리로 자바스크립트를 유용하게 이용할 수 있게 도와준다.

리액트는 응용프로그램을 작은 컴포넌트로 분리, 조합해서 사용(선언형 방식)
-> 유지보수와 관리 향상 복잡한 사용자 인터페이스를 구축하기에 용이하다

Routing

서드 파티 라이브러리 설치 (React-router)

Components & Building UIs

코드를 Component단위로 분리해 관리하면 재사용성, 가독성 향상

react vs reactDOM

  • react : UI라이브러리

  • reactDOM : 웹사이트에 출력을 도와주는 모델

  • React 주요 특징 중 하나는 Virtual DOM을 사용

  • DOM(Document Object Model) 이란?

    객체로 문서 구조를 표현하는 방법으로 XML이나 HTML로 작성한다. 웹 브라우저는 DOM을 활용하여 자바스크립트와 css적용

=> ReactDOM은 브라우저에 대한 리액트 어댑터

페이지가 리로드 되는 과정

  1. 데이터를 업데이트하면 전체 UI를 Virtual DOM에 리랜더링 한다.
  2. 이전 Virtual DOM에 있던 내용과 비교
  3. 바뀐 부분만 실제 DOM에 적용

주요 특징

  • 리액트는 단방향 데이터 플로우를 가지고 있다.
  • 데이터는 항상 일정한 장소에 위치하고, 그 장소에서만 변경 가능!
  • 선언적 접근 방법(state정의 -> 상태 처리)
  • reactDOM은 컴포넌트를 출력(Render)하고, Component는 항상 render, return 해야 함
  • react app은 하나의 component만 rendering (App Component)

public/index.html <- 여기에 src/index.js 가 붙여주는 방식
=> Single Page Application

Tip!

  • import시 js파일은 확장자 생략 가능, css파일은 생략 불가능

JSX(JavaScript XML)

  • return으로 반환되는 Component / JSX는 반드시 root요소를 가진다.
  • css 이름을 적용할 때 - classname으로 이름 지정

React Naming

  • 소문자로 시작하는 요소는 내장된 html요소 -> Component는 대문자로 시작

Components

  • 자바스크립트 표현식 작성 시 JSX내부에서 {}로 감싸면 된다.
  • 부모 컴포넌트로 부터 자식 컴포넌트로 값을 전달시 props로 사용
  • 여러개의 컴포넌트를 하나의 컴포넌트로 조합해 사용 -> 합성(Composition)
  • Wrapper Component - 여러 컴포넌트를 감싸는 방식
  • props.children 자식 엘리먼트를 출력에 전달 가능

Working with Events, state & props

  • 리액트는 모든 기본 이벤트를 on으로 시작하는 props로 나타낸다
  • 모든 이벤트 핸들러는 props값으로 함수 필요
  • 이벤트는 모두 DOM 기본 동작에 기반
  • react 이벤트 종류

onChange vs onInput

onChange은 모든 입력 입력타입에 같은 이벤트 사용 가능

State

리액트는 원하는 state 설정 => state에 맞게 화면 rendering

  • State는 컴포넌트 객체 별로 나뉘어져서 따로 관리된다.

useState

copyButtonText
// useState에서 반환되는 값 1) 상태명, 2) 1에서 정한 상태를 변경하는 함수
const [name, setName] = useState(props.name)

State Update

이전 상태에 따라 상태를 업데이트 할 때 아래 처럼 callback 함수로 구현

copyButtonText
const titleChangeHandler = event => {
  setUserInput(prevState => {
    return { ...prevState, title: event.target.value }
  })
}

Lifting State Up

props로 함수를 넘겨 전달 (자식 -> 부모 컴포넌트로 값 전달)

stateless component

데이터 출력만을 위한 컴포넌트(해당 컴포넌트에서 관리하는 state 없음)

Working with Dynamic Contents

react 컴포넌트 별로 key값을 지정할 수 있음
-> 이렇게 지정하면 업데이트 할 때 특정 위치에 정확히 삽입 가능
-> key가 없으면 값을 추가하는 위치를 정확히 인지하지 못해서 rerendering이 일어남 -> 성능상 이슈
-> 목록 리스트가 존재하면 key값을 주는게 좋다

Rendering List

array 객체의 map함수 이용 동적으로 contents 추가

copyButtonText
const itemfilter = props.items.filter((item) => {
  return item.date.getFullYear().toString() === selectedDate;
});

...

return (
  <div>
    {
      itemfilter.map((item) => <ExpenseItem key={item.id} title={item.title} amount={item.amount} date={item.date} />);
    }
  </div>
)

filter함수를 추가해 조건에 따라 contents 반환 할 수 있다.

Conditional Content

{} 안에 3항 연산자를 사용해 조견별 component 출력이 가능하다

Styling Components

Component에 스타일을 적용하는 방법은 4가지

1) 인라인 요소로 css 추가

html태그의 style속성을 동적으로 줘서 css변경 가능

copyButtonText
let barFillHeight = '20%'

;<div
  className="bar"
  style={{ height: barFillHeight, backgroundColor: 'red' }}
></div>

위 방식대로 style을 주면 인라인 방식이라 코드 가독성이 떨어짐

2) .css파일로 분리

className을 동적으로 변경해서 css 적용 가능
-> 같은 class name을 사용하는 경우 문제

3) Styled Components

서드 파티 라이브러리, 고유한 범위를 가진 스타일로 미리 스타일이 지정된 컴포넌트로 지정 가능

copyButtonText
const FormControl = styled.div`
  margin: 0.5rem 0;
  & label {
    font-weight: bold;
    display: block;
    margin-bottom: 0.5rem;
    color: ${props => (props.invalid ? 'red' : 'black')};
  }s
`
  • styled를 import해 객체를 만들어 사능
  • HTML의 모든 태그가 정의되어 있음
  • props를 전달해 동적으로 변환 가능
  • 미디어 쿼리 적용 가능

4) CSS Module

react css module 사용

copyButtonText
import styles from "./Button.module.css";

...

const Button = (props) => {
  return (
    <button type={props.type} className={styles.button} onClick={props.onClick}>
      {props.children}
    </button>
  );
};
  • 컴포넌트 이름클래스 이름해시 값으로 동적으로 클래스명이 생긴다.

babel-plugin-react-css-modules

Fragments, Portals & Refs

Fragments

리액트는 HTML태그를 트리 구조로 생성하기 때문에 루트 태그가 반드시 필요

빈 div태그로 감싸는 방법 -> 많은 태그들이 생기면서 성능상에도 좋지 않을 수 있음
=> <React.Fragment> 사용

    1. Wrapper 태그 생성
copyButtonText
const Wrapper = props => {
  return props.chilren
}
    1. React.Fragment 사용 - 빈 Wrapper 렌더링
copyButtonText
<React.Fragment>

</React.Fragment>

<>

</>

Portals & Refs

Portals

메인 DOM 외부에 앨리먼트 일부를 그리기 위한 기능 (앨리먼트를 다른 돔으로 옮겨 CSS 상속 구조에 영향 받지 않음)

ex) 모달, 사이드 드로워

copyButtonText
import ReactDOM from "react-dom";

...
return
<React.Fargment>
  // createPortal 함수 사용
  // 1. 렌더링 되는 리액트 노드 (JSX 주의)
  // 2. 렌더링 되어야 하는 실제 DOM 컨테이너 (실제 HTML DOM요소 - Browser API 사용)
  ReactDOM.createPortal(<Backdrop />, document.getElementById('backdrop-root'))
</React.Fargment>

Refs

다른 DOM요소에 접근해 사용 가능

input같은 경우 키 입력마다 state를 변경하는 것은 비 효율적
-> useRef사용

copyButtonText
const inputData = useRef()
  • 모든 훅과 마찬가지로 함수형 컴포넌트에만 사용 가능
  • 사용하고 싶은 태그로 가서 ref 속성 추가
  • 어떤 HTML요소라도 하나에 연결 가능
  • 반환값으로 객체 전달 -> {변수}.current.value 값 사용
  • 입력된 값을 초기화 하고 싶은 경우 유용

Refs값을 재설정 하는 방법

  1. Ref 변수를 직접 변경

  2. stateHandler함수로 state 변경

단순히 값을 변경하는 것으로 Ref 변수를 직접 변경하는 것을 추천

제어 컴포넌트 vs 비제어 컴포넌트

React에 의해 값이 제어되는 입력 폼 엘리먼트 “제어 컴포넌트 (controlled component)“ ex) input, textarea, select

copyButtonText
// 제어 가능한 컴포넌트 -> 항상 최신값으로 유지
<input type="text" value={title || ''} onChange={titleChangeHandler} />
// 비 제어 컴포넌트 -> 필드에서 값을 트리거해 값 사용
<input id="age" type="number" ref={ageInputRef} />

제어 가능한 컴포넌트 -> 항상 최신값으로 유지
비 제어 컴포넌트 -> 필드에서 값을 트리거해 값 사용

기능 제어 컴포넌트 비제어 컴포넌트
일회성 정보 제출 O O
제출 시 값 검증 O O
실시간 필드 값 검사 O X
조건부로 제출 버튼 비 활성화 O X
실시간 입력 형식 적용 O X
동적 입력 O X

Tip!!

npm error 날 경우

copyButtonText
$ npm cache clean --force
$ rm -rf node_modules package-lock.json
$ npm install

객체에 Number 저장

간혹가다 숫자로 객체를 생성하려다가 문자열로 생성되는 경우가 있는데
+를 붙여줘 형변환이 일어나게 저장하면 문제 해결 가능

copyButtonText
const data = {
  name : name,
  age : +age
  date : date
}

함수에 언더스코어(_)를 붙여서 만듬

-> 이유는, 리액트는 자체 기능이 많기 때문에 리액트 자체기능과 구분하기 위해서

Reference

Thank You for Visiting My Blog, I hope you have an amazing day 😆
© 2023 Ian, Powered By Gatsby.