react-dom
이라는 패키지에서 디폴트로 export하는 객체를 ReactDOM
이라는 이름으로 import함class
속성은 className
이라고 해줘야 함for
속성은 반복문과 이름이 겹쳐서 htmlFor
라고 해줘야 함onBlur=""
, onFocus=""
, onMoueDown=""
root.render(
<h1 className = "hello">안녕 리액트!</h1>,
document.getElementById('root')
);
{}
를 사용하면 자바스크립트 표현식을 사용할 수 있음import ReactDOM from 'react-dom';
const product = 'MacBook';
const model = 'Air';
const imageUrl =
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/MacBook_with_Retina_Display.png/500px-MacBook_with_Retina_Display.png';
function handleClick(e) {
alert('곧 도착합니다!');
}
ReactDOM.render(
<>
<h1>{product + ' ' + model} 주문하기</h1>
<img src={imageUrl} alt="제품 사진" />
<button onClick={handleClick}>확인</button>
</>,
document.getElementById('root')
);
import ReactDOM from 'react-dom';
ReactDOM.render(
<button onClick= ... >클릭!</button>,
document.getElementById('root')
);
data-*
속성은 카멜 케이스(Camel Case)가 아니라 기존의 HTML 문법 그대로 작성해야 함import ReactDOM from 'react-dom';
ReactDOM.render(
<div>
상태 변경:
<button className="btn" data-status="대기중">대기중</button>
<button className="btn" data-status="진행중">진행중</button>
<button className="btn" data-status="완료">완료</button>
</div>,
document.getElementById('root')
);
import ReactDOM from 'react-dom';
ReactDOM.render(
<form>
<label htmlFor="name">이름</label>
<input id="name" className="name-input" type="text" />
</form>,
document.getElementById('root')
);
{}
를 활용하면 자바스크립트 표현식을 넣을 수 있음import ReactDOM from 'react-dom';
const product = 'MacBook';
const model = 'Air';
const imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/MacBook_with_Retina_Display.png/500px-MacBook_with_Retina_Display.png'
function handleClick(e) {
alert('곧 도착합니다!');
}
ReactDOM.render(
<>
<h1>{product + ' ' + model} 주문하기</h1>
<img src={imageUrl} alt="제품 사진" />
<button onClick={handleClick}>확인</button>
</>,
document.getElementById('root')
);
import ReactDOM from 'react-dom';
const element = <h1>안녕 리액트!</h1>;
console.log(element);
ReactDOM.render(element, document.getElementById('root'));
import ReactDOM from 'react-dom';
function Hello() {
return <h1>안녕 리액트</h1>;
}
const element = (
<>
<Hello />
<Hello />
<Hello />
</>
);
ReactDOM.render(element, document.getElementById('root'));
// App.js
import Dice from './Dice';
function App() {
return (
<div>
<Dice color="red" num={2} />
</div>
);
}
export default App;
// Dice.js
import diceBlue01 from './assets/dice-blue-1.svg';
import diceBlue02 from './assets/dice-blue-2.svg';
// ...
import diceRed01 from './assets/dice-red-1.svg';
import diceRed02 from './assets/dice-red-2.svg';
// ...
const DICE_IMAGES = {
blue: [diceBlue01, diceBlue02],
red: [diceRed01, diceRed02],
};
function Dice({ color = 'blue', num = 1 }) {
const src = DICE_IMAGES[color][num - 1];
const alt = `${color} ${num}`;
return <img src={src} alt={alt} />;
}
export default Dice;
props
에는 children
이라는 조금 특별한 프로퍼티(prop, 프롭)가 있음children
값에 담기게 됨props
의 속성값을 주로 활용하고, 화면에 보여질 모습을 조금 더 직관적인 코드로 작성하고자 할 때 children
값을 활용할 수가 있음children
을 활용하면 단순히 텍스트만 작성하는 걸 넘어서 컴포넌트 안에 컴포넌트를 작성할 수도 있고, 컴포넌트 안에 복잡한 태그들을 더 작성할 수도 있음// Button.js
function Button({ children }) {
return <button>{children}</button>;
}
export default Button;
// App.js
import Button from './Button';
import Dice from './Dice';
function App() {
return (
<div>
<div>
<Button>던지기</Button>
<Button>처음부터</Button>
</div>
<Dice color="red" num={2} />
</div>
);
}
export default App;
useState
라는 함수를 활용해야 함import { useState } from 'react';
// ...
const [num, setNum] = useState(1);
// ...
useState
함수가 초깃값을 아규먼트로 받고 그에 따른 실행 결과로 요소 2개를 가진 배열의 형태로 리턴을 하기 때문임num
)을 지어주고, 두 번째 변수에는 state 이름 앞에 set을 붙인 다음 카멜 케이스로 이름을 지어주는 것(setNum
)이 일반적임import { useState } from 'react';
import Button from './Button';
import Dice from './Dice';
function App() {
const [num, setNum] = useState(1);
const handleRollClick = () => {
setNum(3); // num state를 3으로 변경!
};
const handleClearClick = () => {
setNum(1); // num state를 1로 변경!
};
return (
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={handleClearClick}>처음부터</Button>
<Dice color="red" num={num} />
</div>
);
}
export default App;
gameHistory
state는 배열 값 자체를 가지고 있는 게 아니라 그 배열의 주솟값을 참조하고 있는 때문에 push 메소드로 배열 안에 요소를 변경했다고 하더라도 결과적으로 참조하는 배열의 주솟값은 변경된 것이 아니게 됨// ...
const [gameHistory, setGameHistory] = useState([]);
const handleRollClick = () => {
const nextNum = random(6);
gameHistory.push(nextNum);
setGameHistory(gameHistory); // state가 제대로 변경되지 않는다!
};
// ...
...
) 을 활용하는 것임// ...
const [gameHistory, setGameHistory] = useState([]);
const handleRollClick = () => {
const nextNum = random(6);
setGameHistory([...gameHistory, nextNum]); // state가 제대로 변경된다!
};
// ...
const baseButtonStyle = {
padding: '14px 27px',
outline: 'none',
cursor: 'pointer',
borderRadius: '9999px',
fontSize: '17px',
};
const blueButtonStyle = {
...baseButtonStyle,
border: 'solid 1px #7090ff',
color: '#7090ff',
backgroundColor: 'rgba(0, 89, 255, 0.2)',
};
const redButtonStyle = {
...baseButtonStyle,
border: 'solid 1px #ff4664',
color: '#ff4664',
backgroundColor: 'rgba(255, 78, 78, 0.2)',
};
function Button({ color, children, onClick }) {
const style = color === 'red' ? redButtonStyle : blueButtonStyle;
return (
<button style={style} onClick={onClick}>
{children}
</button>
);
}
export default Button;
import diceImg from './assets/dice.png';
function Dice() {
return <img src={diceImg} alt="주사위 이미지" />;
}
export default App;
import diceImg from './assets/dice.png';
const style = {
borderRadius: '50%',
width: '120px',
height: '120px',
};
function Dice() {
return <img style={style} src={diceImg} alt="주사위 이미지" />;
}
export default App;
import diceImg from './assets/dice.png';
import './Dice.css';
function Dice() {
return <img src={diceImg} alt="주사위 이미지" />;
}
export default App;
import diceImg from './assets/dice.png';
import './Dice.css';
function Dice({ className = '' }) {
const classNames = `Dice ${className}`;
return <img className={classNames} src={diceImg} alt="주사위 이미지" />;
}
export default App;
function Button({ isPending, color, size, invert, children }) {
const classNames = `Button ${isPending ? 'pending' : ''} ${color} ${size} ${invert ? 'invert' : ''}`;
return <button className={classNames}>{children}</button>;
}
export default Button;
function Button({ isPending, color, size, invert, children }) {
const classNames = [
'Button',
isPending ? 'pending' : '',
color,
size,
invert ? 'invert' : '',
].join(' ');
return <button className={classNames}>{children}</button>;
}
export default Button;
npm install classnames
를 입력하면 설치할 수 있음import classNames from 'classnames';
function Button({ isPending, color, size, invert, children }) {
return (
<button
className={classNames(
'Button',
isPending && 'pending',
color,
size,
invert && 'invert',
)}>
{ children }
</button >
);
}
export default Button;
npm init react-app .
npm start (npm run start)
ctrl + c
npm run build
npx serve build