1. 컴포넌트 재사용
app.js
import { useState } from 'react';
import Board from './Board';
import Button from './Button';
function random(n) {
return Math.ceil(Math.random()*n);
}
function App () {
const [myHistory, setMyHistory] = useState([]);
const [otherHistory, setOtherHistory] = useState([]);
const handleRollClick = () => {
const nextMyNum = random(6);
const nextOtherNum = random(6);
setMyHistory([...myHistory, nextMyNum]);
setOtherHistory([...otherHistory, nextOtherNum]);
};
const handleClearClick = () => {
setMyHistory([]);
setOtherHistory([]);
};
return (
<div>
<Button onClick={handleRollClick}>던지기</Button>
<Button onClick={handleClearClick}>처음부터</Button>
<div>
<Board name="나" color="blue" gameHistory={myHistory} />
<Board name="상대" color="red" gameHistory={otherHistory}/>
</div>
</div>
);
}
export default App;
board.js
import Dice from './Dice';
function Board({ name, color, gameHistory}) {
const num = gameHistory[gameHistory.length -1] || 1;
const sum = gameHistory.reduce((a,b) => a+b,0);
return (
<div>
<h1>{name}</h1>
<Dice color={color} num={num} />
<h2>총점</h2>
<p>{sum}</p>
<h2>기록</h2>
<p>{gameHistory.join(',')}</p>
</div>
);
}
export default Board;
2. 리액트가 렌더링하는 방식
- 리액트는 내부적으로 Virtual DOM을 사용
- Virtual DOM은 웹페이지와 실제 DOM 사이에서 중간 매개체 역할을 하는 것
- 기존의 방식으로 화면을 업데이트 하려면 DOM을 직접 수정해야 하는데, 이것은 성능과 비용에 굉장히 많은 영향을 미침
-> 수정할 부분을 DOM의 데이터에서 모두 찾아야 하기 때문
- 리액트는 DOM을 직접 수정하는 것이 아니라 업데이트해야 할 최소한의 부분만을 찾아서 업데이트
3. 인라인 스타일
Button.js
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;
4. CSS 클래스 네임
App.css
.App .App-button {
margin:6px;
}
App.js
import { useState } from 'react';
import Board from './Board';
import Button from './Button';
import './App.css';
function random(n) {
return Math.ceil(Math.random()*n);
}
function App () {
const [myHistory, setMyHistory] = useState([]);
const [otherHistory, setOtherHistory] = useState([]);
const handleRollClick = () => {
const nextMyNum = random(6);
const nextOtherNum = random(6);
setMyHistory([...myHistory, nextMyNum]);
setOtherHistory([...otherHistory, nextOtherNum]);
};
const handleClearClick = () => {
setMyHistory([]);
setOtherHistory([]);
};
return (
<div className="App">
<Button className="App-button" color="blue" onClick={handleRollClick}>던지기</Button>
<Button className="App-button" color="red" onClick={handleClearClick}>처음부터</Button>
<div>
<Board name="나" color="blue" gameHistory={myHistory} />
<Board name="상대" color="red" gameHistory={otherHistory}/>
</div>
</div>
);
}
export default App;
Button.css
.Button {
padding: 14px 27px;
border-radius: 9999px;
outline: none;
font-size: 17px;
cursor: pointer;
}
.Button.blue {
border: solid 1px #7090ff;
color: #7090ff;
background-color: rgba(0, 89, 255, 0.2);
}
.Button.red {
border: solid 1px #ff4664;
color: #ff4664;
background-color: rgba(255, 78, 78, 0.2);
}
Button.js
import './Button.css';
function Button({ className = '', color = 'blue', children, onClick }) {
const classNames = `Button ${color} ${className}`;
return (
<button className={classNames} onClick={onClick}>
{children}
</button>
);
}
export default Button;
5. 디자인을 적용하는 방법
1) 이미지 불러오기
- 이미지 파일은 import 구문을 통해 불러오고, 불러온 이미지 주소를 src 속성으로 사용
import diceImg from './assets/dice.png';
function Dice() {
return <img src={diceImg} alt="주사위 이미지" />;
}
export default App;
2) 인라인 스타일
- 리액트에서 인라인 스타일은 문자열이 아닌 객체형으로 사용
- 프로퍼티 이름은 CSS 속성 이름으로, 프로퍼티 값은 CSS 속성 값으로 씀
- 대시 기호 없이 카멜 케이스로 써야 함
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;
3) CSS 파일 불러오기
- import 구문으로 from 키워드 없이 파일을 불러올 수 있음
import diceImg from './assets/dice.png';
import './Dice.css';
function Dice() {
return <img src={diceImg} alt="주사위 이미지" />;
}
export default App;
4) 클래스네임 사용하기
- CSS 파일에 정의된 클래스명을 className prop에 문자열로 넣어주면 됨
- 재사용성을 위해 className prop을 부모 컴포넌트에서 받으면 더 좋음
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;
6. 편리하게 클래스네임을 쓰는 방법
- classnames 라이브러리 사용
- classnames는 npm을 통해 설치 가능
- npm install classnames을 입력하고 설치한 다음에 import로 불러와서 쓰면 됨
import classNames from 'classnames';
function Button({ isPending, color, size, invert, children }) {
return (
<button
className={classNames(
'Button',
isPending && 'pending',
color,
size,
invert && 'invert',
)}>
{ children }
</button >
);
}
'react' 카테고리의 다른 글
[코드잇] 리액트로 데이터 다루기(1) (0) | 2023.09.02 |
---|---|
[코드잇] 리액트 웹 개발 시작하기 (6) (0) | 2023.09.02 |
[코드잇] 리액트 웹 개발 시작하기(4) (2) | 2023.09.01 |
[코드잇] 리액트 웹 개발 시작하기(3) (0) | 2023.08.31 |
[코드잇] 리액트 웹 개발 시작하기 (2) (0) | 2023.08.30 |