리액트의 기초를 짚고 넘어가본다.
JSX는 리액트에서 사용하는 "리액트 전용 HTML"이라 봐도 되고, 자바스크립트에 XML을 추가한 문법이다.
export default function Home() {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div>Test</div>
</>
)
}
Create next app으로 만든 보일러플레이트의 index.js를 약간 수정한 파일이다. 보듯 <></> 하나로 감싸져있다. 이는 리액트가 내부에서 Virtual DOM 내부 요소의 변화를 감지할 때 효율적으로 비교를 할 수 있도록, 하나의 컴포넌트가 하나의 DOM 트리 구조로 이루어져야 하기 때문이라 한다.
function App() {
return (
<div className="App">
<div className='black-nav'>
<h4>test</h4>
</div>
</div>
);
}
HTML에서는 class를 사용했지만 className을 사용한다. 이외에 font-size도 fontSize로, onclick도 onClick 등으로 바뀐다.
{}
사용하여 자바스크립트 표현식 작성function App() {
const name = 'Percy';
return (
<div>
<div>Hello</div>
<div>{name}!</div>
</div>
);
}
변수, 연산 등 자바스크립트 표현식은 {} 내부에 작성하여 사용한다. 유효한 모든 JS 표현식이 들어갈 수 있다.
style={{속성: '값'}}
식으로 스타일 지정 <div style={{ textAlign: "center", marginTop: "50px" }}>
<h3>아직 작성된 리뷰가 없습니다.</h3>
<Button
href={`/courses/addReview/${courseId}`}
variant="success"
size="sm"
style={{ marginTop: "20px" }}
>
첫 리뷰를 작성해보세요!
</Button>
</div>
내 프로젝트의 코드 일부다. 보이듯 style = {{}}
형식으로 태그에 스타일을 작성한다.
컴포넌트는 리액트로 만들어진 앱을 이루는 최소한의 단위이고, UI/기능을 부품화하여 재사용 가능하게 해준다. 기존 프레임워크들은 위 그림의 MVC (Model-View-Controller) 디자인 패턴으로 이루어져 있는 경우가 많았는데, 사용자가 컨트롤러를 조작하면 컨트롤러가 모델에서 데이터를 받아오고, 그 데이터를 바탕으로 뷰에 시각적 표현을 하는 방식이다. 이 방식은 각 요소의 의존성이 높고, 재활용이 어려운데, 컴포넌트에선 이 MVC의 뷰를 독립적으로 구성하여 재사용이 가능하다.
리액트에서의 컴포넌트는 데이터 (props)를 입력받고, View (state) 상태에 따라 DOM Node를 출력하는 함수로 정의할 수 있다. 리액트의 2가지 컴포넌트 작성법을 알아보자.
class New extends Component {
render () {
return <div>ㅎㅇㅎㅇ</div>;
}
}
export default New;
함수형 컴포넌트에선 컴포넌트 구성 요소, 생명 주기가 모두 포함되어있다. (여기선 render()
) 밑은 복잡한 예시다.
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파일에서 불러올 수 있도록 내보내주기
출처: 갓대희의 작은공간
위 코드에선 프로퍼티, state, 생명주기 함수가 모두 포함되어있고, 이가 필요한 구조의 컴포넌트가 만들어질때 사용된다.
딱봐도 어려워 보인다. 다른 방법이 없을까?
function New() {
return <div>ㅎㅇㅎㅇ</div>;
}
export default New
훨씬 간단해졌다. 화살표 함수처럼 아래로도 가능하다:
const New = () => <div>ㅎㅇㅎㅇ</div>;
export default New
그럼 왜 애초에 함수형이나 쓸것이지 클래스형을 이케 오래 쓴걸까? Hooks에 대해 알아보며 왜인지 알 수 있다.
함수형은 함수 안에 정의된 것들만 돌려줄 수 있지, 클래스형에서 있던 코드들의 기능은 할 수가 없다. 이를 위해 Hooks가 리액트 v16.8에 도입되어, 함수형 컴포넌트에서도 기존의 함수형 컴포넌트에서 할 수 없었던 작업들을 할 수 있게 되었다. 훅을 사용하는데엔 크게 두가지 규칙이 있다.
함수 최상위에서만 Hook을 호출할 수 있다.
반복문, 조건문, 중첩된 함수 내에서 Hook을 호출 할 수 없다. 이래야 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
오직 React 함수 내에서만 Hook을 호출해야 한다.
일반적인 자바스크립트 함수에서 훅을 호출하면 안된다.
이런 훅들 몇가지를 알아보자.
State는 컴포넌트 전용 변수라 보면 된다.
useState
훅을 통해 우리는 함수형 컴포넌트에서 상태를 관리 할 수 있다. 사용법을 보자.
import { useState } from 'react'
const [state, setState] = useState('Percy');
위의 코드를 나눠서 보면 state
는 변수명, setState
는 state
를 바꿔주는 함수 (세터_, useState
는 훅이고, 훅 안의 값은 state
의 초기값이다.
보통 변수 명을 정하고, 바꿔주는 함수를 set변수명 식으로 이름짓는다. 그래서 이 친구는 왜 쓰는것인가? 컴포넌트에서 동적으로 변수의 상태가 바뀌어야 한다면 자바스크립트라면 document.getElementById()
같은 함수를 쓰면서 바꿔야 하는데, 그 수고를 덜어준다고 보면 된다.