- React 정의 및 설치
- DOM 작성
페이스북에서 개발한 오픈소스 라이브러리
- 사용자 인터페이스(UI) 구축에 사용
- 대규모 애플리케이션&데이터 잦은 변경에 높은 성능
- Vue와의 공통점: 컴포넌트 기반 아키텍처 사용
▶️ 높은 재사용성과 유지보수 - Vue와의 차이점: Vue는 프레임워크, React는 라이브러리 기반 개발 도구
명령어 및 설치 과정
node.js및 npm 설치
- Node.js
▶️ 해당 링크에서 LTS 설치 시 npm 함께 설치
react-app설치
$ npx create-react-app my-app- 리액트 앱 시작
$ cd my-app
$ npm start
# 코드 초기화
$ rm -f src/*- 참고링크: React로 대화형 틱택토 구현하기
# React app 설치
$ npm install -g create-react-app
$ create-react-app firstapp
$ npm start
# 코드 초기화
$ cd my-app
$ rm -f src/*- 비고: npm업데이트 문제로 해결을 위해 npm cache app 설치됨
- JSX 문법으로 작성(Javascript + return(HTML))
- 컴포넌트 이름은 항상 대문자로 시작
- HTML 태그는 소문자로 시작
- 컴포넌트 생성 및 중첩
- 하나의 컴포넌트는 여러 개의 JSX태드를 반환할 수 없다.(
<div></div>또는<></>부모로 감싸야 함)
// 컴포넌트 생성
function MyButton() {
return (
<button>I'm a button</button>
);
}
// 컴포넌트 중첩: MyApp 안에 MyButton 중첩하기
// export default: 파일의 기본 컴포넌트 지정
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<br />
{/* JSX: HTML과 달리 모든 태그를 닫아야 함 */}
<MyButton />
</div>
);
}function MyButton() {
return (
<button classname="avatar">I'm a button</button>
);
}.avatar {
border-radius: 50px;
}function Name() {}사용하여 함수 정의export default로 함수 내보내기- 컴포넌트 안에 다른 컴포넌트 정의 불가
▶️ 최상위 레벨에서 컴포넌트 정의
function Hello () {
return (
<div>
<button>Click!</button>
</div>
)
};
export default Hello; // 컴포넌트 사용가능- Default export 방식: 특정 파일에서 기본적으로 export하는 컴포넌트 사용
- Name export방식: 파일 내 특정 컴포넌트 사용
// App.js
import Hello from './Hello'; // Default import
import { Goodbye } from './Hello'; // Name import
function App() {
return (
<div>
<Hello />
<Goodbye />
</div>
);
}
export default App;
// Hello.js
function hello() {
const click = function (event) {
alert('Hello, world!')
}
return (
<button onClick={click}>click me!</button>
)
}
export function Goodbye () {
const click = function (event) {
alert('Goodbye, world!')
}
return (
<button onClick={click}>Don't click me!!</button>
)
} // Name export
export default hello; // Default export- JSX: JavaScript 안에서 HTML 마크업 실행(컴포넌트 역할)
- 컴포넌트 생성 및 다수 element 반환 시, 하나의 부모 태그로 감싸기 > 기본적으로 html이 아닌 JS 객체로 변환되기 때문
- 모든 태그는 닫아야 함
- 변수명은 Camel Case로 작성(
aria-*,data-*) 제외 - Tip: html과 svg를 JSX로 변환하는 변환기 사용가능 JSX변환기
<!-- 변환 전 -->
<ul>
<li>Invent new traffic lights
<li>Rehearse a movie scene
<li>Improve the spectrum technology
</ul>// 변환 후
export default function TodoList() {
return (
<>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</>
);
}- attribute 정적 지정: 따옴표("", '')로 묶기
- attribute 동적 지정: 중괄호({})로 묶기(함수 호출 가능)
- JSX 태그 안의 문자,
=바로 뒤에 오는 속성만 단일 중괄호 사용 - ex:
<h1>{name}'s To Do List</h1>,src={avatar}
- JSX 태그 안의 문자,
- Object 및 CSS 인라인 스타일: 이중 중괄호
- 사실 JSX 단일 중괄호 안에 JS객체(중괄호로 구성)가 들어있는 구조라 문법상으로는 다르지않음..
function formatDate(date) {
return new Intl.DateTimeFormat(
'en-US',
{ weekday: 'long' }
).format(date);
} // 함수작성
export default function Avatar() {
const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
const description = 'Gregorio Y. Zara';
return (
<h1 style={{backgroundColor: 'black', color:'pink'}}>Today: {formatDate(today)}</h1>
<img
className="avatar" // 정적 지정
src={avatar} // 동적 지정
alt={description}
/>
);
}- 여러 표현식을 하나의 Object로 옮겨서 참조 가능
const person = {
name: 'SSAFY',
theme: {
backgroundColor: 'black',
color: 'pink'
}
}- props: 부모-자식 간 정보 통신 수단
- 부모 컴포넌트: props 전달 / 자식 컴포넌트: props read
- 자식 컴포넌트 지정 시, 인자 기본값 설정 가능(
props={undefined}으로 전달될 때만 사용) - props 속성명과 자식 컴포넌트 속성명이 일치할 시 spread(
{...props}) 사용가능
function Avatar({ person, size = 100 }) { // 원래 props만 인자로 받지만, 구조분해 할당으로 상속받음. size 기본값: 100
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
// 원래 상속되는 모습
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
function Profile(props) { // spread 문법
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
export default function Profile() {
return (
<div>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
<Profile
size={200}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
</div>
);
}{children}prop을 통해 JSX 태그 내 컨텐츠 중첩 가능
function Card({children}) {
return (
<div className="card">
{children} {/* 부모 컴포넌트에서 임의로 채우는 구멍을 만드는 늑김.. */}
</div>
)
}
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
</Card>
)
}- props는 페이지 렌더링마다 새로운 버전의 props 전달받음
- props 데이터가 사용자와 상호작용할 경우, props 자체 변경이 아닌 state를 설정해야 한다.
if,&&,?:연산자로 조건부 JSX 렌더링 가능- 아무것도 반환하지 않을 땐
return null이나&&활용 &&사용 시, 조건을 숫자로 두지 않기(0으로 조건을 걸면 0=false가 아닌 0 자체로 인식하여 반환함)
// if 사용법
if (bool_name) {
return ( {/* bool_name이 True일때 출력하는 요소 */} );
// 반환X -> return null
}
return ( {/* bool_name이 False일때 출력하는 요소 */} );
// 삼항 연산자(?:) 사용법
return (
<li className="item">
{bool_name ? {/* bool_name이 True일때 */} : {/* bool_name이 False일때 */}}
</li>
);
// && 활용
return (
<li className="item">
{name} {bool_name && 'bool_name=true일때 추가로 렌더링할 요소'}
</li>
);
// 변수 조건부 활용
let content = name;
if (bool_name) {
content = (<del>name</del>)
}
return <li>{content}</li>- JS sequence 메서드 사용하여 유사한 컴포넌트 반복 표시 가능:
filter(),map()
const listname = [a, b, c, d] // 데이터 배열 정의
export default function List () {
const listItems = listname.map(item =>
<li key={item.id}>{item}</li> // 반복 시 항상 key 지정
) // listname의 요소들을(item) listItems에 매핑
return <ul>{listItems}</ul>
} // listItems 반환- 반복 시 필수 요소인 key: 항상 고유한 값을 가지고, 변경 허용하지 않음(DB 항목 간 식별 기능)
- React: 모든 components == pure 가정하고 동작함
- React 컴포넌트 input에 대해 항상 같은 JSX 반환
- Side Effect: 컴포넌트 렌더링 전 정의한 객체or변수 변경 시 발생하는 버그
let guest = 0;
function Cup() {
// 컴포넌트 렌더링 시 변수값 변경: 버그 발생 위험
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}- 해결 방법: 렌더링 시 local에서 객체 생성하여 변경
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaGathering() {
let cups = []; // 빈 배열: cup 생성하여 push
for (let i = 1; i <= 12; i++) {
cups.push(<Cup key={i} guest={i} />);
}
return cups;
}

