해당 블로그를 참고해 작성한 글입니다
What is React?
React는 자바스크립트 라이브러리로 SPA(Single Page Application)을 위한 사용자 인터페이스를 구축하는 데 사용된다.
웹, 모바일 앱 등의 view layer를 처리하는 데 사용되며 페이지를 다시 로드하지 않고 데이터를 변경할 수 있도록 가상 돔(Virtual DOM)을 사용하여 웹 애플리케이션의 퍼포먼스를 최적화한 라이브러리이다.
Quick Start
https://cocoon1787.tistory.com/771
[React] 리액트 시작하기
🚀 빠르게 리액트 프로젝트를 시작하는 방법에 관한 포스팅입니다. 1. Node.js와 NPM 설치하기 https://nodejs.org/en/ Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. nodejs.org 위의 사이트
cocoon1787.tistory.com
Feature of React
1. 컴포넌트 ( Component )
React는 컴포넌트 기반의 라이브러리로 웹 페이지에서 컴포넌트는 화면을 이루는 작은 요소들을 말한다.
컴포넌트는 여러 화면에서 재사용될 수 있으며 클래스형과 함수형으로 나뉜다.
1) 클래스형 : 프로퍼티, state와 함수 등을 포함한다.
2) 함수형 : state를 포함하지 않으며 데이터를 받아 출력할 컴포넌트를 반환한다.
2. Props and State
React는 데이터의 흐름이 단방향이다. 즉 위에서 아래, 부모에서 자식, 한 방향으로만 흐르며 거꾸로 부모의 데이터를 바꿔주기 위해서는 state를 이용해야 한다.
1) Props : 프로퍼티(properties)의 줄임말로 부모 요소에서 설정한다. 부모 컴포넌트에서 자식 컴포넌트로 전달해주는 데이터를 Props라고 한다. 읽기 전용이며 자식 컴포넌트에서 전달받은 props를 변경하는 건 불가능하고 props를 전달해준 최상위 부모 컴포넌트만 props를 변경할 수 있다.
2) State : 컴포넌트의 상태를 나타내며 Props와 반대로 변할 수 있다. 즉 동적인 데이터를 다룰 때 사용한다. (리스트에서 선택된 값, 체크박스에서 체크된 값 등) 위에서 언급한 것과 같이 state는 클래스형 컴포넌트에서만 사용할 수 있고 각각의 state는 독립적이기 때문에 다른 컴포넌트의 직접적인 접근이 불가능하지만 상위 state는 state를 변경해주는 함수를 props로 받을 경우 state의 변경이 가능하다.
3. 가상 돔 ( Virtual DOM )
DOM 업데이트를 추상화시켜놓은 것. 브라우저에서 HTML을 열게 되면 DOM을 만들게 되고 HTML 코드의 특정 부분이 변경되면 전체 DOM을 새롭게 만들게 되어 비효율적이다. 이를 개선하기 위해 React는 가상 DOM을 만들어 진짜 DOM과 비교하고, 변경된 부분만 진짜 DOM에 반영하는 방식으로 작업을 수행한다.
4. JSX
JSX(JavaScript XML)는 Javascript에 XML을 추가해 확장한 문법으로 React에서 element를 제공해준다.
간단한 예시로 다음과 같은 형태를 띤다.
function App() {
return (
<h1>Hello World!</h1>
);
}
JSX는 React로 프로젝트를 개발할 때 사용되므로 공식적인 자바스크립트 문법은 아니다.
브라우저에서 실행하기 전에 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환된다.
// 실제 작성할 JSX 예시
function App() {
return (
<h1>Hello, GodDaeHee!</h1>
);
}
// 위와 같이 작성하면, 바벨이 다음과 같이 자바스크립트로 해석하여 준다.
function App() {
return React.createElement("h1", null, "Hello, GodDaeHee!");
}
JSX는 하나의 파일에 자바스크립트와 HTML을 동시에 작성하여 편리하며, 가독성이 높고 작성하기 쉽다.
1) JSX 문법
Ⅰ. 반드시 부모 요소 하나가 감싸는 형태여야 한다.
-Virtual DOM에서 컴포넌트 변화를 감지할 때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있다.
ex ) 에러코드
// Fail to compile
// parsing error : adjacent JSX elements be wrapped in an enclosing tag
// Did you want a JSX fragment <>...</>?
function App() {
return (
<div>Hello</div>
<div>GodDaeHee!</div>
);
}
ex) 정상 코드 (<div></div>)
// div를 사용 하였기 때문에 스타일 적용시 작성한 코드를 div로 한번 더 감쌌다는 부분을 고려해야 한다.
function App() {
return (
<div>
<div>Hello</div>
<div>World!</div>
</div>
);
}
ex) 정상 코드 (<Fragment></Fragment>)
// <Fragment>를 사용가능 하지만 <div>태그보다 무거운 편이다.
function App() {
return (
<Fragment>
<div>Hello</div>
<div>World!</div>
</Fragment>
);
}
ex) 정상 코드 (<></>)
function App() {
return (
<>
<div>Hello</div>
<div>World!</div>
</>
);
}
Ⅱ. 자바스크립트 표현식
- JSX 안에서도 자바스크립트 표현식을 사용할 수 있다. 자바스크립트 표현식을 작성하려면 JSX 내부에서 코드를 { }로 감싸주면 된다.
-유효한 모든 JavaScript 표현식을 넣을 수 있다.
function App() {
const name = 'Balhyo';
return (
<div>
<div>Hello</div>
<div>{name}!</div>
</div>
);
}
- JSX 내부의 자바스크립트 표현식 내에서는 if문이나 for문을 사용할 수 없어서, 조건부 연산자(삼항 연산자)를 사용한다.
function App() {
const name = '리액트';
return (
<div>
{name === '리액트'? (
<h1>리액트</h1>
) : (
<h2>리액트가 아님</h2>
)}
</div>
);
}
Ⅲ. React DOM은 HTML 어트리뷰트 이름 대신 camelCase 프로퍼티 명명 규칙을 사용한다.
ⅰ) JSX 스타일링
- JSX에서 자바스크립트 문법을 쓰려면 {}를 써야 하기 때문에 스타일을 적용할 때에도 객체 형태로 넣어주어야 한다.
-카멜 표기법으로 작성해야 한다. (font-size => fontSize)
ex) css style
function App() {
const style = {
backgroundColor: 'green',
fontSize: '12px'
}
return (
<div style={style}>Hello, GodDaeHee!</div>
);
}
ⅱ) class 대신 className
-일반 HTML에선 CSS 클래스를 사용할 때에 class라는 속성을 사용한다. 하지만 JSX에서는 class가 아닌 className을 사용한다.
ex) className
function App() {
const style = {
backgroundColor: 'green',
fontSize: '12px'
}
return (
<div className="testClass">Hello, GodDaeHee!</div>
);
}
Ⅳ. 주석
- JSX 내에서 {/*...*/}와 같은 형식을 사용한다. 시작 태그를 여러 줄로 작성 시, 그 내부에서 //를 사용하여 주석을 작성할 수도 있다.
<div
className="classEx1" // 주석 작성 가능
>
</div>
5. 뷰 담당 역할 라이브러리
React는 프레임워크가 아닌 라이브러리이며, 뷰만을 신경 쓰는 라이브러리로 기타 기능은 직접 구현하여 사용해야 한다.
React에서는 라우팅을 리액트 라우터, Ajax 처리에는 axios 혹은 fetch, 상태 관리에는 리덕스(redux)나 MobX 등을 사용한다.
React Component
1. React Component란?
리액트로 만들어진 앱을 이루는 최소한의 단위
기존의 웹 프레임 워크는 MVC방식으로 분리해 관리하여 각 요소의 의존성이 높아 재활용이 어렵다는 단점이 있었다. 반면 컴포넌트는 MVC의 뷰를 독립적으로 구성하여 재사용을 할 수 있고 이를 통해 새로운 컴포넌트를 쉽게 만들 수 있다.
컴포넌트는 데이터(props)를 입력받아 View(state) 상태에 따라 DOM Node를 출력하는 함수.
컴포넌트 이름은 항상 대문자로 시작하도록 한다.
(리액트는 소문자로 시작하는 컴포넌트를 DOM 태그로 취급하기 때문이다.)
UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 나누어 코딩한다.
"props"라고 하는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지를 기술하는 React 엘리먼트를 반환한다.
1) 함수형 컴포넌트 ( Stateless Functional Component )
가장 간단하게 컴포넌트를 정의하는 방법은 자바스크립트 함수를 작성하는 것이다.
ex) 함수형 컴포넌트 예시
import React from 'react';
function MyComponent(props) {
return <div>Hello, {props.name}</div>;
}
export default MyComponent; //다른 JS파일에서 불러올 수 있도록 내보내주기
위 예시의 export 구문은 작성한 해당 파일을 다른 파일에서 import 할 때 MyComponent 컴포넌트를 불러올 수 있도록 정의해 주는 부분이다.
import 시 js, jsx 등 파일 확장자를 생략해도 자동으로 찾을 수 있다.
2) 클래스형 컴포넌트 ( Class Component )
컴포넌트 구성 요소, 리액트 생명주기를 모두 포함하고 있다.
프로퍼티, state, 생명주기 함수가 필요한 구조의 컴포넌트를 만들 때 사용한다.
import React from 'react';
class MyComponent extends React.Component {
constructor(props) { // 생성함수
super(props);
}
componentDidMount() { // 상속받은 생명주기 함수
}
render() { // 상속받은 화면 출력 함수, 클래스형 컴포넌트는 render() 필수
return <div>Hello, {this.props.name}</div>;
}
}
export default MyComponent; //다른 JS파일에서 불러올 수 있도록 내보내주기
함수형 컴포넌트가 사용하기 더 쉬워 보이지만 함수형 컴포넌트로 하지 못하는 작업을 처리할 때가 있다.
2. 간단한 실습 - 레이아웃 나누기
Header, Main, Footer로 간단하게 레이아웃 나눠보자.
1) src에 component 폴더를 생성한다.
2-1) 함수형 컴포넌트 생성
해당 폴더 하위에 Header.js, Footer.js, Main.js 생성
import React from 'react';
function Header(props) {
return (
<div>
<header>
<h1>헤더입니다.</h1>
</header>
</div>
);
}
export default Header; //다른 JS파일에서 불러올 수 있도록 내보내주기
import React from 'react';
function Footer(props) {
return (
<div>
<footer>
<h1>푸터입니다.</h1>
</footer>
</div>
);
}
export default Footer; //다른 JS파일에서 불러올 수 있도록 내보내주기
import React from 'react';
function Main(props) {
return (
<div>
<main>
<h1>안녕하세요. 갓대희 입니다.</h1>
</main>
</div>
);
}
export default Main; //다른 JS파일에서 불러올 수 있도록 내보내주기
2-2) App.js에서 해당 컴포넌트 조합하기
import React, { Component } from 'react'; // 리액트를 구현할 수 있는 플러그인을 연결
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
// JS파일에 외부 파일을 불러오는 것이기 때문에 "import" 키워드를 사용한다.
// 같은 JS파일은 확장자를 사용하지 않는다.
function App() {
return (
<div>
<Header />
<Main />
<Footer />
</div>
);
}
export default App; //다른 JS파일에서 불러올 수 있도록 내보내주기
2-3) 결과 화면
3-1) 클래스형 컴포넌트 생성
Header.js, Footer.js, Main.js 생성
import React, { Component } from 'react';
class Header extends Component {
render() { //HTML을 웹 페이지에 렌더링 한다.
return (
<div>
<header>
<h1>헤더입니다.</h1>
</header>
</div>
);
}
}
export default Header; //다른 JS파일에서 불러올 수 있도록 내보내주기
import React, { Component } from 'react';
class Footer extends Component {
render() {
return (
<div>
<footer>
<h1>푸터입니다.</h1>
</footer>
</div>
);
}
}
export default Footer; //다른 JS파일에서 불러올 수 있도록 내보내주기
import React, { Component } from 'react';
class Main extends Component {
render() {
return (
<div>
<main>
<h1>안녕하세요. 갓대희 입니다.</h1>
</main>
</div>
);
}
}
export default Main; //다른 JS파일에서 불러올 수 있도록 내보내주기
3-2) App.js에서 해당 컴포넌트 조합하기
import React, { Component } from 'react'; // 리액트를 구현할 수 있는 플러그인을 연결
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
// JS파일에 외부 파일을 불러오는 것이기 때문에 "import" 키워드를 사용한다.
// 같은 JS파일은 확장자를 사용하지 않는다.
function App() {
return (
<div>
<Header />
<Main />
<Footer />
</div>
);
}
export default App; //다른 JS파일에서 불러올 수 있도록 내보내주기
3-3) 결과 화면
React props
1. React props란?
프로퍼티, props(properties의 줄임말).
상위 컴포넌트가 하위 컴포넌트에 값을 전달할 때 사용한다. ( 단방향 데이터 흐름을 갖는다. )
프로퍼티는 수정할 수 없다는 특징이 있다. (자식 컴포넌트 입장에선 읽기 전용인 데이터이다. )
2. 사용 방법
프로퍼티에 문자열을 전달할 때는 큰따옴표(" ")를, 문자열 외의 값을 전달할 때는 중괄호({ })를 사용한다.
1) 1개의 프로퍼티 넘기기
앞서 3개의 컴포넌트를 만들어 다음과 같은 화면을 구성하였다.(Header, Main, Footer)
단순한 하드 코딩을 props를 통해 개선해보자.
App 컴포넌트에서 Main 컴포넌트에 "name"이라는 이름, "갓대희" 값을 갖고 있는 프로퍼티를 넘겨보자.
ex) App.js (문자열은 큰따옴표( " " ) 를 사용하여 값을 전달한다.)
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
function App() {
return (
<div>
<Header />
<Main name="갓대희"/>
<Footer />
</div>
);
}
export default App;
ex) Main.js (함수형)
import React from 'react';
function Main(props) {
return (
<div>
<main>
<h1>안녕하세요. {props.name} 입니다.</h1>
</main>
</div>
);
}
export default Main;
2) 2개의 프로퍼티 넘기기
이름 이외에 글씨 색상 props를 전달해보자.
ex) App.js (N개의 프로퍼티 전달이 가능하다.)
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
function App() {
return (
<div>
<Header />
<Main name="갓대희" color="blue"/>
<Footer />
</div>
);
}
export default App;
ex) Main.js
import React from 'react';
function Main(props) {
return (
<div>
<main>
<h1 style={{color: props.color}}>안녕하세요. {props.name} 입니다.</h1>
</main>
</div>
);
}
export default Main;
props.를 다음과 같이 생략 가능하기도 하다. (javascript의 비구조화 할당 문법 사용)
ex) Main.js
import React from 'react';
function Main({name, color}) { // props 대신 비구조화 할당
return (
<div>
<main>
<h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
</main>
</div>
);
}
export default Main;
3) 숫자 프로퍼티 넘기기
문자열 대신 숫자를 넘겨 보자.
ex) App.js (문자열 이외에는 중괄호({ }) 사용)
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
function App() {
return (
<div>
<Header />
<Main name={9} color="blue"/>
<Footer />
</div>
);
}
export default App;
3. 프로퍼티의 자료형, 타입 정의
프로퍼티의 자료형을 미리 선언할 수 있다.
리액트에서 제공하는 prop-types를 이용하여 각각의 자료형을 선언하면 된다.
name 프로퍼티는 문자만 올 수 있도록 선언해보자.
ex) Main.js ( 문자열 이외의 프로퍼티 전달 시 경고 노출 )
import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.
function Main({name, color}) {
return (
<div>
<main>
<h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
</main>
</div>
);
}
// 프로퍼티 타입 지정
Main.propTypes = {
name: PropTypes.string
}
export default Main;
아래와 같이 경고 메세지가 나타난다. (다시 변수를 문자열로 바꾸면 경고가 사라진다.)
4. 프로퍼티 기본값 설정 및 필수 값 설정
1) 기본값 설정
컴포넌트에 props 기본값을 설정하고 싶은 경우 defaultProps를 설정하면 된다.
ex) Main.js (name 프로퍼티가 없는 경우, '디폴트'라는 값을 사용하게 처리)
import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.
function Main({name, color}) {
return (
<div>
<main>
<h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
</main>
</div>
);
}
// 프로퍼티 타입 지정
Main.propTypes = {
name: PropTypes.string
}
// 프로퍼티 기본값 지정
Main.defaultProps = {
name: '디폴트'
}
export default Main;
ex) App.js
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
function App() {
return (
<div>
<Header />
<Main color="blue"/>
<Footer />
</div>
);
}
export default App;
2) 필수값 설정
디폴트 설정을 하지 않는 경우 해당 프로퍼티를 필수 프로퍼티로 선언할 수도 있다.
ex) Main.js (isRequired 를 통한 필수 값 설정)
import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.
function Main({name, color}) {
return (
<div>
<main>
<h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
</main>
</div>
);
}
// 프로퍼티 타입 지정 및 필수값 설정
Main.propTypes = {
name: PropTypes.string.isRequired,
}
export default Main;
다음과 같은 경고 메세지가 나오는 것을 볼 수 있다.
5. 불리언 프로퍼티 사용하기
true, false만 정의 가능한 자료형
중괄호로 감싸 전달할 필요 없이 프로퍼티의 이름만 선언하면 된다.
ex) Main.js (maleYn이 true인 경우 '남자', false인 경우 '여자')
import React from 'react';
import PropTypes from 'prop-types'
function Main({color, name, maleYn}) {
const msg = maleYn ? '남자' : '여자'; // 불리언 사용
return (
<div>
<main>
<h1 style={{color}}>안녕하세요. {name} 입니다. ({msg})</h1>
</main>
</div>
);
}
Main.propTypes = {
name: PropTypes.string
}
Main.defaultProps = {
name: '디폴트'
}
export default Main;
ex) App.js
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
import Wrapper from './component/Wrapper';
function App() {
return (
<div>
<Header />
<Main name="갓대희" color="blue" maleYn/>
<Footer />
</div>
);
}
export default App;
App.js에서 mailYn을 생략하면 false로 처리한다.
ex) App.js
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
import Wrapper from './component/Wrapper';
function App() {
return (
<div>
<Header />
<Main name="갓대희" color="blue"/>
<Footer />
</div>
);
}
export default App;
6. props.children 활용하기
children을 사용하여 내부에 있는 내용을 표현할 수 있다.
ex) Wrapper.js
import React from 'react';
import Main from './Main';
function Wrapper(props) {
const style = {
backgroundColor: 'yellow',
};
return (
<div style={style}>
</div>
);
}
export default Wrapper;
기존에 사용하고있던 Main컴포넌트를 감싸 보자. 메인 컴포넌트가 보이지 않게 된다.
ex) App.js
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
import Wrapper from './component/Wrapper';
function App() {
return (
<div>
<Header />
<Wrapper>
<Main color="blue"/>
</Wrapper>
<Footer />
</div>
);
}
export default App;
Wrapper컴포넌트에서 this.children을 렌더링 해보자.
ex) 1번째 방법 ( props.children 사용 )
import React from 'react';
function Wrapper(props) {
const style = {
backgroundColor: 'yellow',
};
return (
<div style={style}>
{props.children}
</div>
);
}
export default Wrapper;
ex) 2번째 방법 (비구조화 할당 문법 사용)
import React from 'react';
function Wrapper({children}) {
const style = {
backgroundColor: 'yellow',
};
return (
<div style={style}>
{children}
</div>
);
}
export default Wrapper;
여러 개의 자식을 사용할 수도 있다.
ex) App.js
import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';
import Wrapper from './component/Wrapper';
function App() {
return (
<div>
<Header />
<Wrapper>
<Main name="갓대희" color="blue"/>
<Main name="갓댐희" color="black"/>
</Wrapper>
<Footer />
</div>
);
}
export default App;
반대로 하나의 자식만 요구할 수도 있다.
ex) Wrapper.js (propTypes 활용)
import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.
function Wrapper(props) {
const style = {
backgroundColor: 'yellow',
};
return (
<div style={style}>
{props.children}
</div>
);
}
Wrapper.propTypes = {
children: PropTypes.element.isRequired
};
export default Wrapper;
다음과 같은 경고 메시지가 나오는 것을 볼 수 있다.
React state
1.React state란?
일반적으로 컴포넌트의 내부에서 변경 가능한 데이터를 관리해야 할 때에 사용한다.
프로퍼티(props)의 특징은 컴포넌트 내부에서 값을 바꿀 수 없다는 것이었다. 하지만 값을 바꿔야 하는 경우도 분명히 존재하며 이럴 때 state라는 것을 사용한다.
값을 저장하거나 변경할 수 있는 객체로 보통 이벤트와 함께 사용된다.
컴포넌트에서 동적인 값을 state라고 부르며 동적인 데이터를 다룰 때 사용된다 볼 수 있다.
1) 선언 방법
react 모듈에서 { useState }를 불러오고 useState()를 선언해서 사용하면 된다.
useState의 변숫값이 바뀌면 컴포넌트가 새롭게 렌더링 된다.
const [state, setState] = useState(initialState);
const [ 데이터, 데이터 변경 함수 ] = useState(초기값(생략 가능));
2) 객체(Object)도 상태 변수(State Value)로 사용 가능하다.
3) useState를 호출하여 반환된 업데이트 함수는 setState와 유사하게 사용 가능하다.
호출한 컴포넌트별로 상태 관리가 가능하다.
이벤트 처리 방법
1. 컴포넌트에서 DOM 이벤트 사용
컴포넌트에서 출력된 특정 DOM 객체에 이벤트 컴포넌트가 동작하기 위해선 DOM 이벤트 프로퍼티를 사용해야 한다.
2. 리액트의 이벤트 문법
소문자 대신 카멜 케이스(camelCase)를 사용한다.
onClick={changename} (x)
onClick={changeName} (o)
JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다.
onClick="changeName()" (x)
onClick={changeName} (o)
함수를 직접 선언하여 사용할 수도 있다.
3. 이벤트의 기본 동작 방지 처리
React에서는 false를 반환해도 기본 동작을 방지할 수 없다.
반드시 preventDefault를 명시적으로 호출해야 한다.
React 반복문 사용하기
1.map() 함수이란?
반복되는 컴포넌트를 렌더링 하기 위하여 자바스크립트 배열의 내장 함수인 map()을 사용한다.
파라미터로 전달된 함수를 사용하여 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 새로운 배열을 생성한다.
2. 문법
arr.map(callbackFunction, [thisArg])
arr.map(callbackFunction(currenValue, index, array), thisArg)
1) callbackFunction : 새로운 배열의 요소를 생성하는 함수로서 다음 세 가지 인수를 갖는다.
- currenValue : 현재 배열(arr) 내의 값들을 의미
- index : 현재 배열 내 값의 인덱스를 의미
- array : 현재 배열
2) thisArg(선택항목) : callback 함수 내부에서 사용할 this 레퍼런스를 설정한다.
3. Component 배열로 map 적용하기
map()을 사용하여 Component를 나타내어 보자.
ex) Main
import React from 'react';
const Main = (props) => {
return (
<div>
<h3>안녕하세요. {props.name} 입니다.</h3>
</div>
);
};
export default Main;
Main 컴포넌트를 Map()를 사용하여 반복해 사용해보자.
ex) App
import React from 'react';
import Main from './Main';
const App = () => {
const names = ["갓대희", "김대희", "한대희"]
const nameList = names.map((name) => (<Main name={name}/>))
return (
<div>
{nameList}
</div>
);
}
export default App;
2차원 배열로도 응용 가능하다.
4. key 설정하기
위의 예제대로만 작성한 경우 다음과 같은 오류 메시지를 볼 수 있다.
( Each child in a list should have a unique "key" prop.)
결론적으로 key를 생성하라는 건데 key는 무엇일까?
1) 사용 목적 : 요소의 리스트를 만들 때, React에서 컴포넌트를 렌더링 할 때 어떤 아이템이 변경되었는지 빠르게 감지하기 위해 사용한다.
map 함수 인잘 전달되는 함수 내부에서 컴포넌트 props를 설정하는 것과 같이 작성한다.
key는 요소의 고유한 값이어야 한다. 배열 요소의 고유한 값을 사용하거나 index로 사용한다.(단, index는 배열의 순서가 바뀌면 index도 바뀌기 때문에 권하지 않는다.)
ex) App
import React from 'react';
import Main from './Main';
const App = () => {
const names = [
{userName : "갓대희", age : 19},
{userName : "김대희", age : 29},
{userName : "한대희", age : 39}
]
const nameList = names.map(v => (<Main key={v.userName} name={v.userName} age={v.age}/>));
return (
<div>
{nameList}
</div>
);
}
export default App;
-경고가 사라진다.
5. 더미 데이터 사용하기
DB 폴더를 생성하고, 하위 파일로 data.json 파일을 생성하여 다음 내용을 입력해보자.
ex) data.json
{
"users" : [
{"userName" : "갓대희", "age" : 19},
{"userName" : "김대희", "age" : 29},
{"userName" : "한대희", "age" : 39}
]
}
ex) App 컴포넌트는 다음과 같이 정리하도록 한다.
import React from 'react';
import Main from './Main';
const App = () => {
return (
<div>
<Main />
</div>
);
}
ex) Main 컴포넌트에서 db를 사용해보자.
import React from 'react';
import dummy from "../db/data.json";
const Main = (props) => {
return (
<div>
{dummy.users.map(user => (
<h3 key={user.userName}>안녕하세요. {user.userName}({user.age}) 입니다.</h3>
))}
</div>
);
};
React Router
1. 라우팅이란?
간단히 말하자면 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이다.
※ SPA, SSR, SSG 등의 대한 개념을 어느 정도 갖춘 상태에서 다음 내용을 진행하는 것을 추천한다.
리액트는 SPA (Single Page Application) 방식
- 기존 웹 페이지처럼(MPA 방식) 여러 개의 페이지를 사용, 새로운 페이지를 로드하는 방식이 아니다.
- 새로운 페이지를 로드하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가진다.
React-Router는 신규 페이지를 불러오지 않는 상황에서 각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링 해주는 라이브러리라고 볼 수 있다.
2. 리액트 라우터 (React Router)
사용자가 입력한 주소를 감지하는 역할을 하며, 여러 환경에서 동작할 수 있도록 여러 종류의 라우터 컴포넌트를 제공한다.
이중 가장 많이 사용되는 라우터 컴포넌트는 BrowserRouter와 HashRouter이다.
1) 종류
-BrowserRouter : HTML5를 지원하는 브라우저의 주소를 감지한다.
-HashRouter : 해시 주소를 감지한다.
2) 설치
3) 사용 예시
라우터를 사용하기 전에 먼저 쇼핑몰이라고 가정하여 샘플 페이지를 만들어 보자. (App, 헤더, 메인 페이지, 상품 상세 페이지)
ex) App.js
import React, { Component } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './Header';
import Main from './Main';
import Product from './Product';
const App = () => {
return (
<div className='App'>
<Header />
<Main />
<Product />
</div>
);
}
export default App;
ex) Header.js
import React from 'react';
function Header(props) {
return (
<>
<h1>헤더입니다.</h1>
</>
);
}
export default Header;
ex) Main.js
import React from 'react';
const Main = (props) => {
return (
<>
<h3>안녕하세요. 메인페이지 입니다.</h3>
</>
);
};
export default Main;
ex) Product.js
import React from 'react';
const Product = (props) => {
return (
<>
<h3>상품 페이지입니다.</h3>
</>
);
}
export default Product;
렌더링 결과
현재는 헤더, 메인 페이지, 상품 상세 페이지가 같이 보인다. Router를 활용해보자
3-1) <BrowserRouter> 태그로 컴포넌트 사용하기
-BrowserRouter를 사용할 것이기 때문에, <BrowserRouter> 태그로 컴포넌트를 감싸주자.
-Header는 모두 URL에 공통 적용할 Component로 최상단에 위치할 예정이다.
3-2) <Routes>, <Route> 컴포넌트 사용하기
-<Routes> 컴포넌트는 여러 Route를 감싸서 그중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜주는 역할을 한다.
-<Route>는 path 속성에 경로, element 속성에는 컴포넌트를 넣어 준다. 여러 라우팅을 매칭 하고 싶은 경우 URL 뒤에 *을 사용하면
3-2.1) "/"로 접근 시 메인 페이지(Main.js)를 보여줄 것이다.
3-2.2) "/product/상품번호"로 접근 시 상품 상세페이지(Product.js)를 보여줄 것이다.
3-3) <Link> 컴포넌트 사용하기
-웹 페이지에서는 링크를 보여줄 때 a태그를 사용한다. 하지만 a태그는 클릭 시 페이지를 새로 불러오기 때문에 사용하지 않는다.
-Lin 컴포넌트를 사용하는데, 생김새는 a태그를 사용하지만 History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있다.
-문법 : <Link to="경로"> 링크명 </Link>
-import { Link } from 'react-router-dom';
4. 사전에 정의하지 않은 경로로 접근하는 경우 NotFound 페이지로 이동 처리
ex) App.js - BrowserRouter를 사용해보자.
import React, { Component } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './Header';
import Main from './Main';
import Product from './Product';
import NotFound from './NotFound';
const App = () => {
return (
<div className='App'>
<BrowserRouter>
<Header />
<Routes>
<Route path="/" element={<Main />}></Route>
<Route path="/product/*" element={<Product />}></Route>
{/* 상단에 위치하는 라우트들의 규칙을 모두 확인, 일치하는 라우트가 없는경우 처리 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
</div>
);
};
export default App;
ex) Main.js - Main 모듈에 특정 상품 상세 페이지로 이동하는 링크를 추가하여 주자.
import React from 'react';
import { Link } from 'react-router-dom';
const Main = (props) => {
return (
<>
<h3>안녕하세요. 메인페이지 입니다.</h3>
<ul>
<Link to="/product/1"><li>1번상품</li></Link>
<Link to="/product/2"><li>2번상품</li></Link>
</ul>
</>
);
};
export default Main;
ex) Header.js - "헤더입니다."를 클릭 시 "/" 페이지로 이동할 수 있게 링크를 추가하자.
import React from 'react';
import { Link } from 'react-router-dom';
function Header(props) {
return (
<>
<Link to="/">
<h1>헤더입니다.</h1>
</Link>
</>
);
}
export default Header;
ex) NotFound.js
import React from 'react';
const NotFound = () => {
return (
<div>
404 Error
</div>
);
};
export default NotFound;
* 4개의 모듈을 작성한 후 다음과 같이 접속하면 페이지 분기 처리되는 것을 볼 수 있다.
case 1) 루트 경로 접속 (/)
<Route path="/" element={<Main />}></Route>
case 2) 상품 상세 페이지 접속(/product/*)
<Route path="/product/*" element={<Product />}></Route>
-아직까지 1번 상품, 2번 상품과 상관없이 동일한 상품 페이지가 노출된다.
case 3) 정의하지 않은 경로 접속(/kkkkkk)
<Route path="*" element={<NotFound />}></Route>
5. URL 파라미터와 쿼리 스트링 사용하기
파라미터, 쿼리 스트링을 통해 유동적으로 동작할 수 있다.
ex)
URL 파라미터 : /product/1
쿼리스트링 : /product?product=1&searchKeyword=productName
5-1) URL 파라미터
-/product/:productId와 같이 경로에 :를 사용하여 설정한다.
- URL 파라미터가 여러 개인 경우엔 /product/:productId/:productName과 같은 형태로 설정할 수 있다.
-다음 구문을 사용하는 컴포넌트에 추가하여 사용 가능하다.
import { useParams } from 'react-router-dom';
const { 파라미터명 } = useParams(); // const 변수명 = useParams().파라미터명;
ex) App.js => productId를 파라미터로 받을 수 있게 추가하자.
import React, { Component } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './Header';
import Main from './Main';
import Product from './Product';
import NotFound from './NotFound';
const App = () => {
return (
<div className='App'>
<BrowserRouter>
<Header />
<Routes>
<Route path="/" element={<Main />}></Route>
<Route path="/product/:productId" element={<Product />}></Route>
{/* 엘리먼트의 상단에 위치하는 라우트들의 규칙을 모두 확인하고, 일치하는 라우트가 없다면 이 라우트가 화면에 나타나게 됩니다. */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
</div>
);
};
export default App;
ex) Product.js => useParams를 통해 App.js에 추가 productId를 받아 활용 가능하다.
import React from 'react';
import { useParams } from 'react-router-dom';
const Product = () => {
const { productId } = useParams();
return (
<>
<h3>{productId}번 상품 페이지 입니다.</h3>
</>
);
}
export default Product;
*파라미터를 통해 상품 ID를 활용할 수 있게 되었다.
5-2) 쿼리 스트링
5-2-1) useLocation
-hash : 주소의 #문자열 뒤의 값
-pathname : 현재 주소 경로
-search :?를 포함한 쿼리 스트링
-state : 페이지로 이동 시 임의로 넣을 수 있는 상태 값
-key : location 객체의 고유 값, 초기값은 default, 페이지가 변경될 때마다 고유의 값이 생성된다.
ex) Product.js
import React from 'react';
import { useParams } from 'react-router-dom';
import { useLocation } from 'react-router-dom';
const Product = () => {
const productId = useParams().productId;
const location = useLocation();
return (
<>
<h3>{productId}번 상품 페이지 입니다.</h3>
<ul>
<li>hash : {location.hash}</li>
<li>pathname : {location.pathname}</li>
<li>search : {location.search}</li>
<li>state : {location.state}</li>
<li>key : {location.key}</li>
</ul>
</>
);
}
export default Product;
-샘플 url
https://localhost:3000/product/1?search=productName&q=demo#test
5-2-2) useSearchParams
ex)
import React from 'react';
import { useParams } from 'react-router-dom';
import { useSearchParams } from 'react-router-dom';
const Product = () => {
const productId = useParams().productId;
const keyWords = searchParams;
const keyWord = searchParams.get("search");
return (
<>
<h3>{productId}번 상품 페이지 입니다.</h3>
<ul>
<li>keyWords : {keyWords}</li>
<li>keyWord : {keyWord}</li>
</ul>
</>
);
}
export default Product;
-결과 페이지
6.useNavigate
Link 컴포넌트를 사용하지 않고 다른 페이지로 이동을 해야 하는 경우, 뒤로 가기 등에 사용하는 Hook이다.
replace 옵션을 사용하면 페이지를 이동할 때 히스토리를 남기지 않는다.
ex)
import React from 'react';
import { useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
const Product = () => {
const productId = useParams().productId;
const navigate = useNavigate();
return (
<>
<h3>{productId}번 상품 페이지 입니다.</h3>
<ul>
<li><button onClick={() => navigate(-2)}>Go 2 pages back</button></li>
<li><button onClick={() => navigate(-1)}>Go back</button></li>
<li><button onClick={() => navigate(1)}>Go forward</button></li>
<li><button onClick={() => navigate(2)}>Go 2 pages forward</button></li>
<li><button onClick={() => navigate('/')}>Go Root</button></li>
<li><button onClick={() => navigate('/', {replace: true})}>Go Root</button></li>
</ul>
</>
);
}
export default Product;