전체내용 : Hello World - React
1. JSX
const element = <h1>Hello, world!</h1>;
위의 태그문법은 문자열, HTML이 아니다. Javascript를 확장한 문법인 **JSX**
이다.
<> ~ </>
부분
1) 특징
- JavaScript의 모든 기능 포함
- UI생김새를 설명하기 위해 React와 함께 사용 권장
- React element를 생성함
- 컴파일 후, JSX 표션식이 정규 JS함수 호출이 되고, JS객체로 인식됨
- camelCase 프로퍼티 명명 규칙 사용
- JSX의 중괄호{} 안에는 모든 유효한 JavaScript 표현식을 넣을 수 있음
ex) name, 2+2, getName(user) , ...
cf) React
React에서는 이벤트가 처리되는 방식, 시간에 따라 state가 변하느 방식, 화면에 표시하기 위해 데이터가 준비되는 방식 등 렌더링 로직이 본질적으로 다른 UI로직과 연결된다는 사실을 받아들인다.
기본적으로 React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 이스케이프 한다. 모든 항목은 렌더링 되기 전에 문자열로 변환된다. (→ XSS(cross-site-scripting) 공격 방지 가능)
2) 객체표현
const element = (
<h1 className="greeting">
Hello
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
위 두 코드는 같은 결과 (객체생성 → React 엘리먼트)
2. 엘리먼트 (Element) 렌더링
1) 엘리먼트
const element = <h1>이것이 엘리먼트다.</h1>;
- React 앱의 가장 작은 단위
- 엘리먼트는 화면에 표시할 내용 기술한다.
- 특정 시점의 UI (영화에서의 하나의 프레임과 비슷)
- 일반 객체 (Plain object). 쉽게 생성 가능
- React DOM은 React엘리먼트와 일치하도록 DOM업데이트
- 엘리먼트는 컴포넌트의 구성요소
2) DOM에 엘리먼트 렌더링
HTML 파일 어딘가에 있는 <div>
<div id="root"></div>
이 안에 들어가는 모든 엘리먼트를 React DOM에서 관리함 ⇒ 루트DOM노드
라고 부른다.
- React로 구현된 애플리케이션은 보통 하나의 루트DOM노드가 있다. (여러 개의 독립된 루트DOM노드가 있을 수도)
-
React 엘리먼트를 루트DOM노드에 렌더링 하려면, 둘 다
ReactDOM.render( )
로 전달const element = <h1>Hello</h1>; ReactDOM.render(element, document.getElementByID('root'));
3) 렌더링 된 엘리먼트 업데이트
React 엘리먼트는 불변객체이다. (생성이후에는 자식, 속성을 변경할 수 없음) 오직 특정 시점의 UI를 보여준다. 따라서, 여기까지 기준으로 UI를 업데이트하기 위해서는 새로운 엘리먼트를 생성하고, ReactDOM.render()로 전달하는 방법 뿐!
실제로 대부분의 React앱은
ReactDOM.render()
를 한 번만 호출한다.
4) 변경된 부분만 업데이트
React DOM는 DOM을 원하는 상태로 만드는데 필요한 경우에만(ex. 변화가 생긴) DOM을 업데이트한다.
3. Components and Props
1) 컴포넌트
- UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 살펴볼 수 있다.
- 개념적으로 JavaScript의 함수와 유사함
props(속성을 나타내는 데이터)
라는 객체 인자를 받아React 엘리먼트
로 반환- 컴포넌트의 이름은 항상 대문자로 시작한다.
컴포넌트를 정의하는 아래의 두 가지 방법은 동일하다.
1. JavaScript함수로 정의하는 방법
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
"함수 컴포넌트"라고 호칭함
2. ES6 class를 사용하여 정의하는 방법
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
(1) 컴포넌트 렌더링
React 엘리먼트는 사용자 정의 컴포넌트로도 나타낼 수 있다.
const element = <Welcome name="Sara" />;
// 여기서 props -> {name: 'Sara'}
React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX어트리뷰트와 자식을 해당 컴포넌트(여기서는 Welcome
)에 단일 객체로 전달한다. 이 객체를 "props"
라고 한다.
이때, props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 짓는 것을 권장한다. (ex. name이라는 props 이름은 Welcome 컴포넌트의 관점!)
(2) 컴포넌트 합성
- 컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있다.
- 일반적으로 새 React 앱은 최상위에 단일 App 컴포넌트를 갖고 있다.
(3) 컴포넌트 추출
- 컴포넌트를 여러 개의 작은 컴포넌트로 나누기
- 구성요소들을 모두 중첩하는 구조보다, 몇 가지 컴포넌트로 나누는 것을 추천한다.
(컴포넌트를 변경하고 구성요소들을 재사용하기 편해진다.)
2) Props는 읽기 전용
- 컴포넌트에서는 자체 props를 수정해서는 안 된다!!
-
모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야 한다.
순수함수 : 입력값을 바꾸지 않고, 항상 동일한 입력값에 대해 동일한 결과를 반환하는 함수
4. State와 생명주기
props와 유사하지만, 비공개이며 컴포넌트에 의해 완전히 제어된다.
1) 클래스 컴포넌트로 state를 사용할 수 있다.
ES6 class로 컴포넌트를 사용한다.
render메서드는 업데이트가 발생할 때마다 호출되지만, 같은 DOM노드로 해당 클래스(ex. <Clock />
)를 렌더링하는 경우, 그 클래스의 단일 인스턴스만 사용된다.
이를 통해 로컬 state, 생명주기 메서드 등과 같은 부가적인 기능을 사용할 수 있다.
사용방법
- 클래스로 컴포넌트를 작성한다.
-
생성자 추가 ( props 전달 방식 집중! )
constructor(props) { super(props); this.state = {date: new Date()}; }
클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 한다.
this.props
대신this.state
사용- props를 삭제한다.
<Welcome name="Sara" />
→<Welcome />
2) 생명주기메서드 추가하기
생명주기 메서드를 이용해서 컴포넌트가 마운트되거나 언마운트 될 때 일부 코드를 작동할 수 있다.
componentDidMount()
컴포넌트 출력물이 DOM에 렌더링 된 후에 실행된다.componentWillUnmount()
this.setState()
컴포넌트 로컬 state 업데이트
사용방법 예시
다음 링크의 예시 참고 Hello World in React
<Clock />
가ReactDOM.render()
로 전달되었을 때 React가 Clock 컴포넌트의constructor
을 호출한다.- Clock컴포넌트의
render()
메서드 호출 → React는 화면에 표시될 내용을 알게 됨 → DOM 업데이트 - Clock출력값이 DOM에 삽입되면
componentDidMount()
메서드 호출 → 이 안에서 매초tick()
메서드르를 호출하기 위한 타이머를 설정하도록 브라우저에 요청 - 매초 브라우저가
tick()
메서드 호출함. → 이 안에서setState()
에 현재 시각을 포함하는 객체를 호출하면서 UI 업데이트 → React는state
가 변경된 것을 인지 (setState()덕분) → 화면에 표시될 내용을 알아내기 위해render()
다시 호출 → 이 때 render() 안의this.state.date
가 달라짐. → 렌더링 출력값은 업데이트된 시각을 포함 → React는 이것을 따라 DOM업데이트 함 - Clock 컴포넌트가 DOM으로부터 삭제되면
componentWillUnmount()
메서드 호출 (타이머를 멈추기 위해)
3) State를 올바르게 사용하기
- State를 직접 수정하는 대신
setState()
사용한다.this.state
를 지정할 수 있는 유일한 공간은constructor
- state업데이트는 비동기적일 수 있다. 이때 발생하는 업데이트 실패 문제를 해결하기 위해
setState((state, props) ⇒ ( <내용> );
사용 - state의 독립적인 변수들은 별도의
setState()
호출로 독립적으로 업데이트 할 수 있다.
4) 기타 특징
- 컴포넌트는 자신의 state를 자식 컴포넌트에 props로 전달할 수 있다.