VIEW 단을 책임지는 라이브러리 - 유저 인터페이스를 책임짐
components 단위로 생각하는게 중요하다.
훨씬 더 ‘선언’적이다. Nav Search App VideoList VideoListEntry 하나 하나가 다 컴포넌트. 화면 구성 하나 하나를 다 컴포넌트 단위로 생각해보라.
Javascript 안에 html이 있는 구조. 컴포넌트 하나 하나 그 자체로 완전한 기능을 함. 재사용이 좋아지고, 하나의 컴포넌트 단위로 테스트가 가능.
XML 형식으로 JS를 작성.
React.createElement('div',{className:'red'}, 'Children Text');
-> JSX
<div className="red">Children Text</div>;JSX 태그로 감싸진 녀석들은 모두 컴포넌트
<div className="red">Children Text</div>;
div라는 컴포넌트가 red라는 className을 갖고 있는 형태
html에서 class를 React에서는 className으로 씀
마치 html attribute를 쓰듯이 작성하며 prop에 문자열을 대입하는 경우를
제외하고는 중괄호로 감싸줌.const myProp = { a: 1, b: 2};
<div className="red" myProp={myProp}>Children Text<div>state가 변하면 re-render를 해서, 해당 컴포넌트를 다시 그림.
this.props 및 this.state 가 비동기로 업데이트될 수 있기 때문에, 다음 state를 계산할 때 해당 값을 신뢰해서는 안됩니다.
예를 들어, 카운터를 업데이트하는 이 코드는 실패할 수 있습니다.
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});이 문제를 해결하기 위해 객체가 아닌 함수를 받는 두 번째 형식의 setState() 를 사용할 수 있습니다. 이 함수는 이전 state를 첫번째 인수로 받고, 두번째 인수로 업데이트가 적용 될 때 props를 받습니다.
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));위 예제에서는 arrow function 을 사용했지만, 평범한 함수도 동작합니다.
// Correct
this.setState(function(prevState, props) {
return {
counter: prevState.counter + props.increment
};
});State 업데이트는 병합됨
setState() 를 호출할 때, React는 현재 state와 제공한 객체를 병합합니다.
데이터는 아래로 흐른다!
State는 컴포넌트 자신만 접근할 수 있다. 부모나 자식 컴포넌트에선 접근 할 수 없다. 대신, 컴포넌트는 자신의 state를 자식 컴포넌트에게 props로 내려줄 수 있다.
: 모든 state는 항상 특정 컴포넌트가 가지며, 해당 state에서 파생된 모든 데이터 또는 UI는 트리의 컴포넌트 “아래(below)“에만 영향을 미칩니다.
FormattedDate 컴포넌트는 props에서 date 를 받지만 이 값이 Clock 의 상태인 지, Clock 의 props인 지, 혹은 손으로 입력한 건지 알 수 없습니다.
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}모든 컴포넌트는 실제로 분리되어 있다.
ex) 리액트 튜토리얼 예쩨에서 clock 3개 : 각 clock은 자체적으로 타이머를 생성하고 독립적으로 업데이트 함.
const hello = () => {} 리턴이 필요
const hello = () => () JS의 ()는 컨테이너 역할만 함.
브라켓 {} 문법 = 변수를 넣는 컨테이너 역할
local state는 클래스에서만 사용가능한 기능.
클래스 컴퍼넌트는 항상 props와 함께 기본 생성자constructor를 호출한다.
ReactDOM.render(
<Clock />, <------ 반드시 쉼표 넣어줘야 한다
document.getElementById('root')
);
button = <LogoutButton onClick={this.handleLogoutClick} />;
button = <LoginButton onclick={this.handleLoginClick} />;
// onClick이다. 대소문자 유의하자!!
ReactDOM.render <- 이거 DOM 자꾸 소문자로 쓰는 문제
React.Component // C는 대문자다!react 이벤트는 소문자 대신 camelCase 사용
JSX에 문자열 대신 함수를 전달
React에서 기본 동작을 막기 위해 false 리턴을 사용할 수 없다. 반드시 명시적으로 preventDefault 를 호출해야 합니다. 예를 들어 HTML에서 새로운 페이지를 여는 기본 링크 동작을 막으려면 이렇게 작성할 수 있습니다.
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>React에선
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}React에서는 리스너를 호출하기 위해서 addEventListener를 호출할 필요가 없다. 대신 요소가 처음 렌더링될 때 리스너를 제공한다.
arrow 함수가 항상 좋은 것은 아니다
JSX 콜백에서 this 의 의미에 대해 주의해야합니다. 자바스크립트에서 클래스 메서드는 기본적으로 bind되지 않습니다. 만약 this.handleClick 바인드를 잊은채로 onClick 에 전달하면, this 는 함수가 실제로 호출될 때 undefined 로 취급됩니다.
이건 React에서 정의한 동작이 아닙니다. 자바스크립트의 함수의 동작 방식 의 일부입니다. 일반적으로 onClick={this.handleClick} 처럼 () 없이 메서드를 참조하면, 그 메서드를 bind 해야합니다.
만약 bind 를 호출하는 게 귀찮은 경우 이 문제를 해결할 수 있는 두가지 방법이 있습니다. 만약 실험 기능인 퍼블릭 클래스 필드 문법 을 사용한다면 클래스 필드를 정확히 콜백에 bind할 수 있습니다.
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}이 문법은 Create React App 에서 기본으로 사용할 수 있습니다.
만약 클래스 필드 문법을 사용하고 싶지 않다면, 콜백에서 arrow function 을 사용할 수도 있습니다.
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}이 문법의 문제점은 LogginButton 을 렌더링할 때마다 서로 다른 콜백이 만들어지는 것입니다. 대부분의 경우에서 크게 문제는 없습니다. 하지만 만약 콜백에서 하위 컴포넌트에 prop을 전달하는 경우, 이 컴포넌트는 큰 비용으로 다시 렌더링될 수 있습니다. 이런 종류의 성능 문제를 피하기 위해 보통 생성자 함수에서 바인딩하거나 클래스 필드 문법을 사용하는 걸 권장.
반복 안에서 보통 이벤트 핸들러에 추가 파라미터를 전달하고 싶어할 것입니다. 예를 들어, 만약 id 가 원시적인 ID라면, 아래처럼 전달할 수 있습니다.
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>위 두 라인은 동일하며, arrow functions과and Function.prototype.bind 를 각각 사용하고 있습니다.
두 경우 모두, React 이벤트를 나타내는e 인수는 ID 뒤에 두 번째 인수로 전달됩니다. arrow function을 사용하여 명시적으로 전달해야하지만,bind를 사용하면 추가 인수가 자동으로 전달됩니다.
자바스크립트에서 true && expression 은 항상 expression 으로 평가되고, false && expression 은 항상 false 로 평가되기 때문에 아래 코드는 동작합니다.
조건이 true 라면 && 다음에 오는 요소가 노출됩니다.
만약 조건이 false 라면, React는 이를 무시하고 건너뜁니다.
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>hello1</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
)
}
const messages = ['','react', 're:react', 're:re:react']
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('root')
)아주 예외적인 경우를 제외하고선.
https://hackernoon.com/the-constructor-is-dead-long-live-the-constructor-c10871bea599
setState를 쓰는 이유는 ? 나중에 최적화를 위해서
불변성을 유지시켜서, 변수의 레퍼런스(메모리 주소)만 비교하면 된다
prevState === nextState
아래로 계속 props를 내려줘야 하는 불편함때문에, 어디서나 공유하고 변경할 수 있는 REDUX가 생김. depth가 깊어질수록 redux가… 필요해짐.
return (
<Fragment>
<h1>무얼 마시고 싶니?</h1>
<h2>DATA : {data}</h2>
<input
placeholder="원하시는 것을 입력하세요"
onChange={e => onChange(e)}
/>
<hr />
</Fragment>
)예를 들어, ListItem 컴포넌트를 추출 한 경우, ListItem 자체의 루트 <li> 요소가 아닌 배열의 <ListItem /> 요소가 키를 가지고 있어야합니다. -> map을 부를때 거기서 키를 지정해주는게 좋다.
글로벌로 유니크할 필요는 없습니다. 두 다른 배열을 생성할 때 동일한 키를 사용할 수 있습니다.