const name = 'Yeri Kim'
const element=<h1>Hello,{name}</h1>
중괄호 안에 유효한 모든 JavaScript 표현식(변수, 함수)을 넣을 수 있음
JSX 표현식은 컴파일 후 JavaScript 함수 호출이 되고, 객체로 인식한다.
if, for, 변수, 함수 반환 가능
attribute에 따옴표로 문자열 리터럴 혹은 중괄호로 JavaScript 표현식 삽입 가능
const element = <img name='yeri' src={user.url}></img>
다만, 동일 attribute에 두 가지 동시 사용 불가
또, camelCase 명명 규칙 따름
React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 Escape하므로 명시적이지 않으면 주입되지 않음
모든 항목은 렌더링 전 문자열로 변환됨 → XSS(cross-site-scripting)공격 방지
Babel : JSX를 React.createElement() 로 컴파일 → 결과로 객체 생성함
이 객체는 React Element라 하고, 화면에서 보고 싶은 표현임
이 객체를 통해 DOM을 구성하고 최신으로 유지함
Element : 화면에 표시할 내용 기술, 일반 객체이고 쉽게 생성 가능
React Dom은 이와 일치하도록 DOM을 업데이트한다.
Root DOM 노드가 있음 : 이 안에 들어가는 모든 element를 관리함
→ ReactDOM.rener()로 element를 root DOM 노드에 렌더링하면 됨
ReactDOM.render(element,document.getElementById('root');
React element는 불변 객체, 특정 시점의 ui를 보여주는 것
→ ReactDOM.render()를 새로 호출해야 ui가 업데이트 됨 (유일)
실제로는 한번만 호출됨. state 관리
ReactDOM은 이전의 element와 비교하고 수정된 부분 같이 필요한 경우에만 DOM 업데이트
→ 시간의 변화에 따라 변화하는 것을 고민하는 것보다 수많은 버그를 없앰
function Welcome(props){
return <h1>hello,{props.name}</h1>;
props : 속성을 나타내는 데이터
객체 인자를 받은 후 React element를 반환하므로 유효함
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
React에겐 동일한 컴포넌트다.
사용자 정의 component로 element를 나타낼 수 있음
이 element를 발견하면 JSX attribute와 자식을 컴포넌트에 단일 객체로 전달. 이 객체가 props이다.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
위 코드 실행시
1. element로 render() 호출
2. React는 {name:'Sara'}를 props로 Welcome component 호출
3. 이 component는 hello sara element를 반환
4. ReactDOM은 이 element와 일치하도록 DOM을 효율적으로 업데이트함
컴포넌트의 이름은 항상 대문자
출력에 다른 component를 참조 가능 → 세부 단계에서 동일 추상 컴포넌트 사용 가능
일반적으로 React 앱은 최상위에 단일 App 컴포넌트를 갖고 있음
그래서, 기존 → React : 작은 컴포넌트부터 상단 계층으로 올라가면서 작업 필요
컴포넌트를 여러 작은 것들로 나눠야 함. → 재사용하기 좋아짐
props를 자체적으로 수정하면 안됨. → 입력값을 수정하지 않고 항상 동일한 입력값에 대한 동일한 결과를 반환하므로 순수함수 라고 함.
this.state={date: new Date()};
→ 스스로 타이머 설정 후 매초 스스로 업데이트할 수 있어짐
컴포넌트 삭제시 사용 중이던 리소스를 확보하는 것이 중요
this.setState((state,props)=>{}
위와 같이 객체 보다는 함수를 인자로 사용하는 형태로 사용할 것.<button onClick={activateLasers}>
Activate Lasers
</button>
unreadMessages.length > 0 && <h2>You have {unreadMessages.length} unread messages.</h2>
condition? true:false
map()을 이용하여 numbers 배열 반복 실행하기
순서 없는 엘리먼트 리스트를 출력하는 컴포넌트로 리팩토링할 수 있음
key를 각 항목에 넣어야 함
1. React가 어떤 항목을 crud할지 식별하는 것을 돕는다.
2. 고유성 부여 위해 지정해야 함
list의 index는 최후의 수단..! ➡️ 성능 저하, state 문제가 발생할 수 있다. 지정하지 않으면 default로 사용하긴 함
주변 배열 context에서만 의미가 있다.
map() 내부에 있는 엘리먼트에 넣어줘야 한다!
컴포넌트로 전달하진 않는다. 이용해야한다면 prop으로 명시적 전달이 필요
중괄호 안에 map() 함수의 결과를 인라인으로 처리하기
제어 컴포넌트 방식 이용!
React state를 신뢰 가능한 단일 출처로 만들어 두 요소를 결합할 수 있다. ➡️ 이를 통해 폼에 발생하는 사용자 입력값을 제어
즉, 항상 React state에 의해 input 값이 결정됨
<textarea>
<select>
with <option>
<file>
: 비제어 컴포넌트class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value);
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'};
}
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
문제가 있을 땐 React Developer Tools로 디버깅
React는 강력한 합성 모델을 갖고 있고, 이를 사용해서 코드 재사용하는 것이 좋다.
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
FancyBorder은 {props.children}을 <div>
안에 렌더링하므로 최종 출력됨.
목업으로 시작하기
아무 동작하지 않는 버전을 만들기 ➡️ state 사용하지 않기 (데이터가 바뀌는 것에 사용)
어떤 컴포넌트가 state를 소유할지 찾기
단방향 데이터 흐름임을 기억
1. state 기반 렌더링하는 컴포넌트 찾기
2. 공유 소유 컴포넌트 : 공유 state를 갖는 모든 컴포넌트들의 상위 한 컴포넌트 찾기
3. 항상 더 상위가 가져야 함
4. 찾지 못했다면 state를 소유하는 컴포넌트를 하나 만들어 상위 계층에 추가하기