프론트앤드 개발을 위한 JavaScript 오픈소스 라이브러리이다.
하나의 페이지를 보여주기 위해 HTML, Css, JS로 나눠서 작성하기 보다는
하나의 파일에 명시적으로 작성할 수 있게 JSX (HTML과 JS가 결합한 문법) 를 활용한 선언형 프로그래밍을 지향한다.
하나의 기능 구현을 위해 여러 종류의 코드를 묶어둔 컴포넌트 기반으로 개발한다.
컴포넌트 분리로...
기능 자체에 집중하여 개발할 수 있다.
컴포넌트간 의존성이 낮아 유닛 테스트를 하기 편하다.
컴포넌트의 기능을 보고 에러를 찾을 수 있어서 유지보수가 편하다.
프레임워크는 생태계에 종속되지만 React는 라이브러리라 그렇지 않다.
기존에 JavaScript 프레임워크로 제작된 웹 어플리케이션에 리액트를 추가해서 유연하게 사용가능하다.
Facebook에서 관리되어 안정적이고 유지보수가 잘 되어오고 있다.
React Native를 이용해 모바일 개발도 가능하다.
HTML과 JS가 결합한 문법으로 JSX는 JavaScript가 확장된 문법이지만, 브라우저가 바로 실행할 수는 없다.
브라우저가 이해할 수 있는 JavaScript코드로 컴파일 해주어야 브라우저가 화면에 렌더링 할 수 있다.
이때 이용하는 것이 Babel이다.
JSX 없이 React를 썼을 경우
return React.createElement( "h1", null, `Hello, ${formatName(user)}!` )
JSX를 사용했을 경우
return <h1>hello, {formatName(user)}!</h1>
가독성이 올라가는 것을 알 수 있다.
const posts = [ { id: 1, title : 'Hello world', content : 'welcome to learning React!' } { id: 2, title : 'Installation', content : 'you can install React via npm.' } ... ... ]; function Blog() { const postToElement = (post) => ( <div key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> </div> ); const blogs = post.map(postToElement); return <div className="post-wrapper">{blogs}</div>; }
하나의 기능 구현을 위한 여러 종류의 코드 묶음으로 UI를 구성하는 필수요소이다.
const Component = () => {
return (
<div>
<div>{}</div>
<div>{}</div>
</div>
)
}
컴포넌트를 조합하면 어플리케이션을 만들 수 있다.
리액트 어플리케이션은 컴포넌트들의 관계를 트리 구조를 형상화하여 표현할 수 있다.
독립적인 컴포넌트들을 여러 개 만들고 이들은 한데 모아 복잡한 UI를 구성할 수 있고, 최종적으로는 복잡한 애플리케이션을 만들 수 있다.
리액트 SPA를 개발할 수 있도록 만들어진 툴 체인
npx create-react-app 프로젝트이름
npm을 활용하는 명령어 중 하나다.
실행을 하면 인스톨하는 패키지로
react
와 리액트를 브라우저에 실행할수 있는react-dom
, SPA 구현과 모던프론트앤드기술이 미리 준비되어있는react-script
, 관련 패키지cra-template
가 설치되고 있는것을 확인할 수 있다.
Create React App은 새로운 디랙토리를 알아서 생성을 하고 쉽게 리액트를 개발할 수 있도록 여러 유용한 node-js패키지를 node_modules 디랙토리에 저장한다.
패키지 목록은 pakage.json, package-lock.json 파일에 자세히 적혀있다.
src 디랙토리에는 리액트 프로젝트의 필수적인 파일들이 저장되어있다.
react-scripts start
이나 npm run start
로 실행할 수 있다.
import React from 'react'; import ReactDom from 'react-dom'; import './index.css'; import App from './App'; import ReportWebVitals from './reportWebVitals'; ReactDom.render( //<-------------- HTML DOM에 접근해 HTML 엘리먼트에 넣어준다. <React.StrictMode> <App />{//<------------------- React로 개발한 부분 }, </React.StrictMode>, documnet.getElementById('root') // <------ HTML 엘리먼트에 접근하고 있다. ); ReportWebVitals();
import를 이용해 node-js에 설치된 패키지를 불러오거나 src디랙토리에 있는 js파일을 불러올 수 있다.
새로고침할때마다 랜덤으로 명언을 출력해보자
import './App.css';
funtion App() {
const proverbs = ["명언1", "명언2", "명언3", "명언4", "명언5"]
const getRandomIndex = (length) => {
return paresInt(Math.random() * length);
}
return (
<div className="App">
<header className="App=header">
{proverbs[getRandomIndex(proverbs.length)]}
</header>
</div>
);
}
전통적인 웹사이트는 페이지 이동 시 매번 페이지 전체를 불러와야 했다.
SPA는 HTML문서 전체가 아니라 업데이트가 필요한 부분만 새로 불러온다.
SPA는 하나의 페이지를 가지고 있지만 사실 한 종류의 화면만 사용하지 않는다.
화면에 따라 주소도 달라져야 하며 다른 주소에 따라 다른 뷰를 보여주는 과정을
"경로에 따라 변경한다." 라는 의미로 라우팅(Routing)이라 한다.
라우터 역할을 하는 BrowserRouter,
경로를 매칭하는 역할을 하는 Switch와 Route,
경로를 변경하는 역할을 하는 Link 가 있다.
react-router 라이브러리 설치
npm install react-router-dom@5.3.0
App.js로 react-router 컴포넌트 불러오기
import { BrowserRouter, Switch, Route, Link} from "react-router-dom";
function Home() { return <h1>Home</h1>; } function MyPage() { return <h1>MyPage</h1>; } function Dashboard() { return <h1>Dashboard</h1>; }
페이지를 표시하는 Home, Mypage, Dashboard 컴포넌트들을 만들었다.
function App () { return ( <div> <nav> <ul> <li> Home </li> <li> MyPage </li> <li> Dashboard </li> </ul> </nav> </div> ) } export default App;
각 컴포넌트로 이동할 메뉴를 만들었다.
function App() { return ( <BrowserRouter> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/mypage">MyPage</Link> </li> <li> <Link to="/dashboard">Dashboard</Link> </li> </ul> </nav> <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/mypage"> <MyPage /> </Route> <Route path="/dashboard"> <Dashboard /> </Route> </Switch> </div> </BrowserRouter> ); } function Home() { return <h1>Home</h1>; } function MyPage() { return <h1>MyPage</h1>; } function Dashboard() { return <h1>Dashboard</h1>; } export default App;
컴포넌트의 사용 중 컴포넌트 내부에서 변화하는 값.
애플리케이션의 "상태"로 구분할 수 있다.
React에서 state를 다루는 방법 중 하나로 useState라는 특별한 함수를 제공한다.
예시
function Checkbox() { const [isChecked, setIsChecked] = useState(false); }
isChecked
와 setIsCheched
는 useState
의 리턴값을 구조분해 할당한 변수이다.
풀이
function Checkbox() { const [저장변수, 갱신함수] = useState(초기값); }
state갱신함수 사용 예시
function Checkbox() { const [isChecked, setIsChecked] = useState(false); const handleChecked = (event) => { setIsChecked(event.target.checked); }; return ( <div className="App"> <input type="checkbox" checked={isChecked} onChange={handleChecked} /> <span>{isChecked ? "Checked!" : "Unchecked!"}</span> </div> ); }
React 컴포넌트는 state가 변경되면 새롭게 호출되고, 리렌더링 된다.
React state는 갱신함수 호출로 변경해야한다. 저장변수를 강제로 변경하면 리렌더링이 되지않거나 제대로 변경되지 않는다.
외부로부터 전달받은 값
- 하위 컴포넌트에 전달하려는 값과 속성을 정의한다.
- props를 이용하여 정의된 값과 속성을 전달한다.
- 전달받은 props를 렌더링한다.
function Parent() { return ( <div className="parent"> <h1>I'm parent</h1> <Children text={"I'm first child"} /> <Children>I'm second child</Children> </div> ); } function Children(props) { return ( <div className="children"> <p>{props.text}</p> <p>{props.children}</p> </div> ); } export default Parent;
React의 이벤트 처리방식은 DOM과 유사하지만 몇 가지 문법 차이가 있다.
HTML 방식
<button onclick="handleEvent()">이벤트</buttom>
React 방식
<button onClick={handleEvent}>이벤트</buttom>
Form 엘리먼트(ex. <input>
<textarea>
<select>
) 에 입력된 값을 컴포넌트의 state로 관리하고 업데이트 한다.
예시
function NameForm() { const [name, setName] = useState(""); const handleChange = (e) => { setName(e.target.value); } return ( <div> <input type="text" value={name} onChange={handleChange}></input> <h1>{name}</h1> </div> ) };
<button>
<a>
엘리먼트와 같이 사용자의 행동에 따라 반응 해야할때 사용되는 이벤트이다.
예시
function PopupButton() { const [showPopup, setShowPopup] = useState(false); const togglePopup = () => { setShowPopup(!showPopup) }; return ( <div className="App"> <h1>Fix me to open Pop Up</h1> <button className="open" onClick={togglePopup}>Open me</button> {showPopup ? ( <div className="popup"> <div className="popup_inner"> <h2>Success!</h2> <button className="close" onClick={togglePopup}> Close me </button> </div> </div> ) : null} </div> ); }