<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
React.createElement(
MyButton,
{
color: 'blue,
shadowSize: 2,
}
'Click Me'
)
<div className="sidebar />
React.createElement(
'div',
{ className: 'sidebar' }
)
JSX 태그의 첫 부분은 React element의 타입을 결정한다
대문자로 시작하는 JSX 태그는 React 컴포넌트를 지정한다
이 태그들은 같은 이름을 가진 변수들을 직접 참조한다
만약 <Foo />와 같은 JSX 표현을 쓰려고 한다면 Foo가 반드시 스코프 내에 존재해야 한다
JSX는 React.createElement를 호출하는 코드로 컴파일 되기 때문에 React 라이브러리 역시 JSX 코드와 같은 스코프 내에 존재햐아 한다
아래의 예시를 통해 보면, React와 CustomButton는 Javascript 코드에선 직접적으로 사용되진 않지만 JSX 태그로 사용하기 위해 꼭 import 해야한다
import React from 'react';
import CustomButton from "./CustomButton';
function WarningButton() {
return <CustomButton color="red" />;
}
import React from 'react';
const MyComponents = {
DatePicker: function DatePicker(props) {
return <div>Imagine a {props.color} datepicker here.</div>;
}
}
function BlueDatePicker() {
return <MyComponents.DatePicker color="blue" />;
}
Element가 소문자로 시작하는 경우에는 <div>나 <span> 같은 내장 컴포넌트라는 것을 뜻한다
'div'나 'span'같은 문자열 형태로 React.createElement에 전달된다
<Foo />와 같이 대문자로 시작하는 타입들은 React.createElement(Foo)의 형태로 컴파일 된다
Javascript 파일 내에 사용자가 정의했거나 import한 컴포넌트를 가리킨다
컴포넌트의 이름은 대문자로 시작하는 것을 추천한다
만약 소문자로 시작하는 컴포넌트를 사용해야 한다면, 대문자로 시작하는 변수에 할당한 뒤 JSX에서 이 변수를 사용해라
import React from 'react';
import { PhotoStory, VideoStory } from "./stories";
const components ={
photo: PhotoStory,
video: VideoStory,
};
function Story(props) {
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
JSX 안에서 prop을 사용하는 방법은 여러 가지가 있다
<MyComponent foo={1 + 2 + 3 + 4} />
MyComponent의 props.foo의 값은 1 + 2 + 3 + 4의 표현식이 계산되기 때문에 10이다
if 구문과 for 루프는 Javascript 표현식이 아니기 때문에 JSX 안에서 그대로 사용할 수 없다
하지만 아래의 예시와 같이 JSX 밖의 주변 코드에서 사용할 수 있다
function NumberDescriber(props) {
let description;
if (props.number % 2 == 0) {
description = <strong>even</strong>;
} else {
description = <i>odd</i>;
}
return <div>{props.number} is an {description} number</div>;
}
<MyComponent message="hello world" />
<MyComponent message={'hello world'} />
<MyComponent message="<3" />
<MyComponent message={'<3'}>
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
function App1() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
function App2() {
const props = { firstName: 'Ben', lastName: 'Hector' };
return <Greeting {...props} />;
}
const Button = props => {
const { kind, ...other } = props;
const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
return <button className={className} {...other} />;
}
const App = () => {
return (
<div>
<Button kind="primary" onClick={() => consolke.log("clicked!")}>
Hello World!
</Button>
</div>
)
}
위의 예시에서 kind prop은 소비되고 DOM의 button element에 넘겨지지 않는다
다른 모든 prop은 ...other 객체를 통해서 넘겨지며 이 컴포넌트를 유연하게 만들어 준다
onClick과 children이 prop으로 넘겨지는 것을 볼 수 있다
전개 연산자는 유용하지만 불필요한 prop을 컴포넌트에 넘기거나 유효하지 않은 HTML 속성들을 DOM에 넘기기도 한다
꼭 필요할 때만 사용하자
여는 태그와 닫는 태그가 있는 JSX 표현에서 두 태그 사이의 내용은 props.children이라는 특수한 prop으로 넘겨진다
자식을 넘기는 방법은 여러 가지가 있다
<MyComponent>Hello world!</MyComponent>
<div>This is valid HTML & JSX at the same time.</div>
<div>Hello World</div>
<div>
Hello World
</div>
<div>
Hello
World
</div>
<div>
Hello World
</div>
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
<div>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
render() {
// 리스트 아이템들을 추가적인 엘리먼트로 둘러쌀 필요 없다!
return [
// key 지정을 잊지 마세요 :)
<li key="A">First Item</li>,
<li key="B">Second Item</li>,
<li key="C">Third Item</li>,
]
}
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
function Hello(props) {
return <div>Hello {props.addressee}!</div>;
}
// 자식 콜백인 numTimes를 호출하여 반복되는 컴포넌트를 생성
function Repeat(props) {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i));
}
return <div>{items}</div>;
}
function ListOfTenThings() {
return (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
)
}
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
<div>
{showHeader} && <Header />}
<Content />
</div>
<div>
{props.message.length &&
<MessageList messages={props.messages} />
}
</div>
<div>
{props.message.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
<div>
My Javascript variable is {String(myVariable)}
</div>