-
1. 리액트 시작하기React 2022. 4. 12. 15:52
React – 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리
A JavaScript library for building user interfaces
ko.reactjs.org
목차
1. 리액트의 개념
1-1. 리액트란?
1-2. 기본 세팅
2. 리액트 시작하기
2-0. ReactDOM.render()
2-1. 컴포넌트 만들기(1) : Class
2-2. 컴포넌트 만들기(2) : Function
2-3. Props & State
2-4. lifecycle1. 리액트의 개념
1-1. 리액트란?
- 자바스크립트 라이브러리... 이지만 프레임워크라고 해도 됨.
- 페이스북에서 만든 오픈소스 프로젝트
- 프론트엔드에서 사용자 인터페이스(UI)를 만드는데 사용됨
- MVC 구조에서 view에 해당
- ✔️ Component : 원하는 형태로 만든 뒤 재사용을 할 수 있는 HTML 덩어리 👉 class나 함수에 담아서 사용한다!
- ✔️ Props & State : 컴포넌트에 데이터를 담고 조작할 수 있음
1-2. 기본 세팅
(1) HTML파일 세팅
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>리액트 배우기</title> <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> // 👉 리액트 코드를 여기에 </script> </body> </html>
1. React, ReactDOM, Babel의 CDN을 head내에서 로드해준다.
- React : React의 최상위 API. 리액트 문법을 쓸 수 있게 해줌.
- ReactDOM : adds DOM-specific methods (정확히 뭔지 모르겠음. 최종적으로 브라우저에 랜더링해주는 역할. 전체 엘리먼트 내에서 변화가 있는 부분을 찾고 그 부분을 조작해줌)
- Babel : ES6+ 문법을 오래된 브라우저에서도 사용할 수 있게 해주는 컴파일러. HTML 엘리먼트를 JS 영역내에서 사용할 수 있게해줌.
2. 기본이 되는 root div를 넣어준 뒤 아래에 script를 작성한다. 이때 type을 text/javascript가 아닌 text/babel로 해줌으로써 CDN 링크로 가져온 Babel을 사용할 수 있게 된다.
2. 리액트 시작하기
2-0. ReactDOM.render()
ReactDOM.render(<App />, document.querySelector('#root')
ReactDOM.render는 작성해둔 컴포넌트를 DOM에 렌더링하는 역할로, 스크립트 내 가장 마지막에 써주면 된다.
마치 express의 app.listen()처럼 최종적으로 실행을 시켜주는 코드이다.
render메소드는 두가지를 인자로 받는다.
- 인자1 : 넣을 내용
- 인자2 : 넣을 위치
위 코드가 실행되면 가장 최상단 컴포넌트인 App이 root div의 내에 들어가게 된다. (항상 최상단 컴포넌트를 넣어주어야하며 하위의 엘리먼트들은 컴포넌트 내부에 삽입하는 형식)
이 코드도 거의 고정으로 사용하게 되니 여기까지는 외워두면 좋다
인자1을 넣는 방식은 다양하다.
1. React.createElement() 사용
const btn = React.createElement('button', {id: 'btn', class:'btnClass'}, '버튼') ReactDOM.render(btn, root)
세가지의 인자를 받는다.
- 인자1 : 엘리먼트 명 (ex. a, button, input, li... )
- 인자2 : 속성값 object (ex. {id: 'btn', class : 'btnClass', type : 'submit'} )
- 인자3 : innerHTML 내용. 태그의 내부에 들어가는 요소
2. Babel을 이용해 HTML엘리먼트를 변수에 담아서 바로 사용 (JSX)
const id = 'btn' const btn2 = <button id={id} class='btnClass'>버튼2</button> ReactDOM.render(btn2, root)
HTML 형식 그대로 써서 변수에 담을 수 있다.
내부에서 변수를 사용하고 싶으면 {변수명}으로 사용할 수 있다.
3. HTML을 컴포넌트로 담아서 사용 (JSX)
위에서도 적었듯 컴포넌트는 재사용이 가능한 HTML 엘리먼트 덩어리이다. 이를 클래스나 함수에 담아서 사용한다.
초기에는 class 문법을 사용했지만 최근에는 함수로 담는 것이 편리성 면에서 뛰어나 함수를 많이 사용한다.
각각의 장단점이 있는 편이고 함수형을 최근에는 많이 사용한다고 하지만 클래스형 컴포넌트에 대한 개념을 알고 있어야 기존의 코드를 해석하고 사용할 수 있기 때문에 기본적인 개념은 알아두는 것이 좋다.
세부적인 차이는 앞으로 공부를 하면서 차차 배워나갈 예정... 일단 단순한 사용방법에 대한 내용을 아래에서 조금 더 상세하게 설명하겠다.
2-1. 컴포넌트 만들기(1) : class
// 컴포넌트를 만들 때 앞글자는 대문자로!! class App extends React.Component { render() { return ( <div><Table /></div> ) } } ReactDOM.render(<App />, root)
❗️컴포넌트 명의 앞글자를 꼭 대문자로 써줘야한다
1. React.Component 클래스를 상속하여 App이라는 컴포넌트를 만들어준다.
2. render 함수를 선언해준다. 화면에 최종적으로 그릴 내용을 return 해주는 함수이다.
3. 컴포넌트로 만든 HTML은 <'컴포넌트명' />으로 가져와 사용한다.
4. 여러개의 컴포넌트를 중첩해서 사용해야 할 경우 마찬가지로 <'하위컴포넌트명' />을 return해줄 HTML코드 내부에 삽입해준다.
5. 반드시 return 영역은 하나의 최상위 엘리먼트를 가져야한다.
<div>1</div><div>2</div>
이런 형태로는 사용하지 못한다. 만약 이렇게 쓰고 싶다면 가상의 div로 묶어주어야 한다.
class list extends React.Component { render() { // Fragment : 화면에 보이지는 않지만 리액트컴포넌트로 작동만 되게끔 감싸주는 가상 div return ( <li>1</li> <li>2</li> <li>3</li> ) // ❌ 에러발생 } } // Fragment : 화면에 보이지는 않지만 리액트컴포넌트로 작동만 되게끔 감싸주는 가상 div class list extends React.Component { render() { return ( <React.Fragment> <li>1</li> <li>2</li> <li>3</li> </React.Fragment> ) // ⭕️ } }
2-2. 컴포넌트 만들기(1) : function
const App = () => { return ( <div>함수형 컴포넌트는 상속이 필요없다!</div> ) } ReactDOM.render(<App />, root)
함수형 컴포넌트는 상속이 필요없다! 👍 코드가 좀 더 쉬워진다
얘는 일주일동안 클래스형 컴포넌트에 먼저 익숙해진 뒤 자세히 배울 예정이라 필요하다면 나중에 따로 글을 적을 예정이다.
2-3. Props & State
리액트의 가장 중요한 공식이 있다.
데이터가 바뀌면 화면이 바뀐다
여기서 데이터가 바로 Props와 State이고, 화면이 Component이다.
Props와 State에 해당하는 리액트 내의 데이터에 변화가 있으면 해당 Component는 다시 렌더링을 하게되고, 변경된 데이터를 반영하여 새로운 화면을 만들어준다!
Props와 State는 간단히 말하자면
- 상위컴포넌트에서 하위컴포넌트로 데이터를 전달하고 싶다! 👉 Props
- 한 컴포넌트 내에서 데이터(상태값)을 저장하고 싶다! 👉 State
이렇게 구분할 수 있을 것이다.
Props
class Input extends React.Component { // 기존에 사용하던 props 전달받는 방법. 현재는 쓰지 않는 코드이다. constructor(props) { super(props) } render() { // props는 this.props 객체에 저장이 된다. const {name} = this.props return ( <input type="text" value={name} /> ) } } class App extends React.Component { render() { return ( <div> <Input idx={1} name={'hb'} age={'29'} /> </div> ) } }
부모 컴포넌트에서 자식 컴포넌트를 불러올 때 'props명' = { 값 } 의 형태로 데이터를 넘겨준다
넘겨준 데이터는 자식 컴포넌트에서 this.props 내에 객체로 담겨진다.
State
state(상태)는 특정 컴포넌트 내에서 정보를 담아두는 변수이다.
state라는 객체 안에 컴포넌트 내에서 필요한 데이터를 담아두고 이 값들을 변화시키면서 해당 상태에 따라 화면을 다르게 렌더링할 수 있다.
여기서 중요한 것은 state는 객체라는 점이다!
JS 기초문법에서 {} === {} 는 false라는 것을 배웠다. 객체는 그 자체를 값으로 가지는 문자열이나 숫자형 데이터와는 달리 참조형 데이터로 reference를 값으로 가진다. 각 객체는 자기 자신만의 고유한 reference 값을 가진다.
그러면 state는 객체이고, state가 변경되었다는 것을 어떻게 전달해야 할까?
// ❌ : 같은 참조값을 가지므로 state 객체가 변경되었다는 사실을 리액트는 알 수 없다! state = { a: 1 } state.a = 2 // ⭕️ : 스프레드 연산자와 리액트에서 제공하는 setState() 함수를 이용한다. state = { a: 1 } newObj = {...state, a: 2 } this.setState(newObj) // 위 코드는 대략적인 setState 흐름을 나타낸 것이고 실제로 사용하는 리액트 코드는 아래의 코드 참조
실제로 컴포넌트 내에서 state를 사용하여 렌더링 하는 방법은 다음과 같다.
class Login extends React.Component { state = { isLogin: false } render() { const obj = { ...this.state, isLogin: !this.state.isLogin } return ( // 상태에 따라 삼항연산자를 활용해 다른 컴포넌트를 렌더링해 준다 <div> <button onClick={ ()=>{this.setState(obj)} }> {this.state.isLogin ? <TrueState /> : <FalseState />} </button> </div> ) } }
초기값을 false로 설정해 둔 뒤 클릭이 발생할 때마다 불리언인 isLogin의 값이 반대가 되도록 onClick이벤트를 설정해준 뒤,
해당 불리언값에 따라 삼항연산자를 사용해 각 경우에 따른 컴포넌트를 렌더링하도록 해주었다.
기존의 state 객체가 아닌 다른 reference 값을 가진 새 객체를 생성하고, 리액트에서 제공하는 함수인 setState 함수를 이용해 state에 해당하는 객체를 변경해준다. 참조값이 다르니 데이터가 바뀌었다는 것을 인지하고, 데이터가 변했으니 화면을 새롭게 렌더링한다.
'React' 카테고리의 다른 글
4. Redux로 전역 상태 관리하기 (0) 2022.05.02 3. react-router-dom으로 리액트에서 페이지 이동 구현하기 (0) 2022.05.02 2. 커스텀 훅으로 Form 컴포넌트 만들어보기 (0) 2022.04.27