
(!는 sw스터디에서 같이 읽은 내용을 토대로 작성했습니다)
https://reactjs.org
Copyright © 2021 Facebook Inc.
React는 JavaScript(이하 JS) 라이브러리
= JS 기본적으로 공부하고 오셈
-> React에서 추천하는 링크
JSX? 자바스크립트를 확장한 문법!
-> React의 Element를 produce(생성)함
React는 'rendering logic' is coupled with(연결) 'UI logic'라 생각
-> rendering logic + UI logic = "component"를 사용
JSX 안에서 {자바스크립트 표현식} 사용가능
JSX는 컴파일 종료 시, 자바스크립트 함수를 호출하면서 자바스크립트 객체로 인식됨
= JSX도 표현식임
attributes(속성)으로 "문자열" or {자바스크립트 표현식} 사용가능!
HTML < JavaScript에 가까움 -> HTML attribute < 'camemlCase' 사용하셈
자식태그 포함가능
<닫는 태그 /> 반드시 필요
injection attack 방지함
React DOM은 JSX의 삽입된 값을 rendering하기 전에 escape -> never inject anything that’s not explicitly(명시적으로) written
= 모든 항목은 렌더링되기 전에 문자열로 변환
-> XSS 공격 방지
나도 뭔 소린지 모르겠는데, 걍 injection attack을 방지한다는 것만 알면 될 듯
React.createElement() 호출 -> Babel compiles JSX
-> 대충 Babel이 컴파일해서 돌아간다는 뜻
React.createElement()가 대충 버그검사하고 element 객체 생성
element가 뭐임?
const element = {
type: 'tag',
props: {
key: 'value',
}
};
화면에서 보고 싶은 것을 나타내는 애
따라서 React는 Element를 읽어서 DOM을 구성하고 최신상태로 유지하는 라이브러리라 보면 될 듯
Element? 화면에 표시할 내용을 적는 React의 가장 작은 building blocks(대충 단위로 해석하면 될 듯)!
-> React DOM이 React Element와 DOM을 일치하도록 DOM을 업데이트!
React Element는 브라우저 DOM Element와 달리, plain object이며 쉽게 생성가능
Component != Element -> 'Component > Element(Component의 구성요소)'
HTML의 태그 안에 Element를 넣어서 rendering
-> React DOM이 Element를 관리하므로, 이를 'DOM node'라고 부름
보통 React 애플리케이션은 하나의 DOM node가 존재
React를 기존 애플리케이션에 통합할 경우, 다양한 DOM node 존재
React elements은 immutable(불변)해야 함!
= Element 생성 후, 자식이나 속성을 변경이 안 됨!
그럼 UI를 어케 업데이트함?
새 Element를 생성하고, 이를 ReactDOM.render()로 전달!
대부분의 React app은 ReactDOM.render()를 한 번만 호출
즉, immutable = rendering된 경우, 메모리영역을 다시 건들 수 없음!
-> 그럼 어케 바꿈? 아래에 정답!
React DOM은 해당 Element를 이전의 Element와 비교하고, DOM을 원하는 상태로 만드는데, 필요한 경우에만 DOM을 업데이트함
UI를 어떻게 보여주니? React, "Given moment > Over time"!
즉, 어케 바꿈?
-> 'virtual DOM으로 달라진 부분을 체크해서 고놈만 바꿈 > 전체 페이지를 계속 바꿈'
= React는 가장(x) 충분히(o) 빠르다
UI -> independent(개별적인) reusable(재사용 가능한) pieces of 'Components'
Funtions(JavaScript) = Components(React)
props를 입력 -(Components)-> 화면을 보여주는 React Elements를 반환
function FunctionComponent(props) {
return <tag>{props.key}</tag>;
}
class ClassComponent extends React.Component {
render() {
return <tag>{props.key}</tag>;
}
}
React의 관점에서 두 가지 Components가 동일
const element = <tag />;
or
const element = <Component key="value" />
React element -> DOM 태그 or 사용자 정의 component
function Component(props) {
return <tag>{props.key}</tag>;
}
const element = <Component key="value" />;
ReactDOM.render(
element,
document.getElementById('id')
);
React는
소문자로 시작 -> DOM 태그로 처리
대문자로 시작 -> Component로 처리
= Component는 항상 대문자로 시작
Component는 출력에 다른 Component를 refer(참조)할 수 있음
-> Component 결합
Component -(split)-> smaller Components
App이 커질수록 -> reusable Components 굿굿
Component를 얼마나 나누냐에 따라 rendering 횟수가 달라짐
-> 적절한 extracting 필요
Props는 Component가 생성될 때 초기에 받아옴
Component가 절대로 자체 Props를 수정해서는 안 됨!
pure? input을 수정하지 않고, 동일한 input에 동일한 output을 return함
All React component는 반드시 pure function으로 동작해야 함
이는 UI가 동적으로 변하는 것과는 무관하며, state를 통해 이를 위반하지 않고 React Component가 output을 변경할 수 있음
React Component 안의 state와 lifecycle?
렌더링된 출력값을 변경?
-> 지금까지는 ReactDOM.render() 함수 호출하는 식
Component를 완전히 reusable(재사용) + encapsulated(캡슐화)?
Component에 “state”를 추가!
State는 Props와 유사하지만, private(비공개) + fully controlled by the component(컴포넌트에 의해 완전히 제어)
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function -> class
1. React.Component를 extends한 같은 이름의 ES6 class 생성
2. 빈 render() 메소드 추가
3. function의 body(내용)을 render() 메소드 안으로 이동
4. render 안의 props를 this.props로 변경
5. 함수 삭제
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
render는 업데이트마다 호출되지만, 같은 DOM node로 render하는 경우에는 class의 single instance로만 사용됨
-> local state와 lifecycle methods를 사용할 수 있게 함
props -> state로
1. render() 메소드 안에 있는 this.props.key -> this.state.key
2. 최초의 this.state를 지정하는 class constructor를 생성
constructor(props) {
super(props);
this.state = {key: value};
}
class component는 항상 props로 기본 constructor를 호출
3. element에서 key prop을 삭제
components가 삭제되면 사용 중이던 resources를 확보해야 함!
mount? 처음 DOM에 render될 때마다 타이머를 설정하려고 함
unmount? 생성된 DOM이 삭제될 때마다 타이머를 해제하려고 함
component class에서 특정 메소드를 선언하여 component가 mount되거나 unmount될 때 일부 코드를 작동 -> “lifecycle methods”.
componentDidMount() 메소드는 Component output이 DOM에 rendering된 후에 실행 -> 타이머 설정에 좋음
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
data flow 안에 포함되지 않는 항목을 보관하고 싶다면, 자유롭게 class에 manually하게 부가적인 field를 추가 가능!
componentWillUnmount() 메소드
componentWillUnmount() {
clearInterval(this.timerID);
}
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
constructor -> render -> did -> willun
1. <Component이름 />가 ReactDOM.render()로 전달될 때, React가 Component의 constructor를 호출 -> this.state를 초기화
2. React는 component의 화면에 표시할 render() 메소드를 호출 -> React는 rendering output을 일치시키기 위해 DOM을 업데이트
3. 출력값이 DOM에 insert되면, React는 componentDidMount() lifecycle method를 호출. 그 안에서 component는 메소드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청.
4. browser가 타이머에 맞춰 메소드를 호출. 그 안에서, component는 setState() 호출로 UI업데이트를 진행. setState() 호출로, React는 state가 변한 걸 인지하고, 화면에 표시될 내용을 알기 위해 render()메소드를 다시 호출. 이 떄 render 메소드 안의 this.state.key가 달라지고, rendering output은 업데이트를 포함. React는 이에 따라 DOM을 업데이트.
5. Component가 DOM으로부터 삭제된다면, React는 멈추기 위해 componentWillUnmount() lifecycle method를 호출
Do Not Modify State Directly
constructor에서 this.state를 assign + setState()
-> this.state.key = value? component를 다시 렌더링하지 않음
State Updates May Be Asynchronous
React는 setState()를 single 업데이트로 한꺼번에 처리 가능
this.props와 this.state가 asynchronous으로 업데이트될 수 있음 -> state를 계산할 때 해당 값에 의존하면 안 됨
this.setState({
counter: this.state.counter + this.props.increment,
});
->
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
or
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
State Updates are Merged
setState()를 호출할 때, React는 제공한 객체를 현재 state로 merge
this.setState()를 각각 호출하여 independently 업데이트할 수 있음 -> 병합은 shallow하게 이뤄지므로, this.state.key1과 this.state.key2는 각각 업데이트(서로 영향x)
parent component나 child component 모두 특정 component가 stateful이거나 stateless인지 알 수 없음 + function이거나 class이거나 관심 없음
state = local or encapsulated
component가 소유하고 state가 설정한 component 이외에는 어떠한 component도 접근 불가
component는 자신의 state를 child component에 props로 전달가능
-> state로 왔는지, props로 왔는지, 수동으로 입력한지 알 수 없음
= top down or unidirectional data flow -> 모든 state는 항상 특정 component가 소유하며 그 state로부터 파생된 UI나 data는 tree 구조에서 자신의 below에 있는 component에만 영향
tree = props의 폭포
each component의 state = 특정 지점에서 만나지만 동시에 아래로 흐르는 addtional water source
React apps에서 component가 stateful이거나 stateless인 건 시간의 흐름에 따라 바뀔 수 있는 component의 implementation detail stateful component에서 stateless components 사용 가능. 역도 마찬가지
이게 먼저 떠올라야 함
state(상태) -> 이 컴포넌트(자신)의 상태라서 외부에서 접근이 안 됨.
props 받아옴 + 수정불가
setstate?
직접적으로 바꾸지 마세요 + 동기적으로 안 바뀔 수도 있어요