📌 React JS
React JS
왜 써요? 리액트..?
React JS는 UI를 interactive하게 만들어준다.
react는 interactive한 웹 사이트를 구현하기 위해 어떤 것이 필요한지 알고 있다.
때문에 우리는 react를 사용하면서 더욱 쉽게 interactive한 웹 사이트를 구현할 수 있게 된다.
리액트 어떻게 쓰는데요?
script를 import해온다.
리액트와 리액트 돔을 가져오면 된다.
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
위 코드를 쓰고 난 뒤, 실행시켜서 브라우저 개발자 도구에 “react”를 입력하면 아래와 같이 확인할 수 있다.
React element 생성하기
* 현재 배우는 생성 방법은 보편적으로 쉬운 방식이 아님. 그러나 어려운 방식을 통해 리액트에 한 발자국 더 가까워질 수 있음.
<body>
<div id="root"></div>
</body>
<script>
const root = document.getElementById('root');
// react element 생성
const span = React.createElement(
"span",
{ id: "sexy-span" },
"Hello I'm a span"
);
// react DOM을 사용하여 react element를 렌더링한다.
ReactDOM.render(span, root);
</script>
실제로 개발자는 위와 같은 방식으로 리액트 element를 만들지 않는다.
(밑에서 더욱 쉬운 방법을 소개할 예정) 그러나 여기서 말하고자 하는 바는 script단에서 HTML를 Update하기 용이하다.
즉, 유저에게 보여질 내용을 간단하게 컨트롤할 수 있다.
JSX를 사용하여 더욱 똑똑하게 React element 생성하기
JSX는 JavaScript를 확장한 문법으로서 여러 방법으로 활용되지만 특히, React element를 생성할 때 더욱 편리하게 생성할 수 있게 도와준다.
먼저 JSX로 생성한 요소는 어떻게 생겼는지 살펴보자.
// 어트리뷰트에 따옴표를 이용해 문자열 리터럴을 정의할 수 있습니다.
const aTag = <a href="https://www.reactjs.org"> link </a>;
// 중괄호를 사용하여 어트리뷰트에 JavaScript 표현식을 삽입할 수도 있습니다.
const imgTag = <img src={user.avatarUrl}></img>;
// JSX 태그는 자식을 포함할 수 있습니다.
const divTag = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
위처럼 JSX를 활용하여 element를 표현할 수 있다.
그럼 단지 element를 저렇게만 쓰면 React element가 되는 걸까?
아니다. JSX만 작성한다면 무조건 Syntax Error가 발생한다.
Babel를 사용하여 JSX를 React가 이해할 수 있는 형태로 바꿔주기
JSX를 다시 처음 방식의 React element로 변환해주는 작업이 필요하다.
우리는 Babel을 활용하여 이 과정을 해줄 수 있다.
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
babel을 import하면 JSX를 우리가 처음 만들었던 형태의 React element로 변환해준다.
아래 예시 코드를 살펴보자.
<body>
<div id="root"></div>
</body>
<script type="text/babel">
const root = document.getElementById('root');
let counter = 0;
const onClickEvent = () => {
counter = counter + 1;
render();
};
const render = () => {
ReactDOM.render(<Container />, root);
};
const Container = () => (
<div>
<h3>Total: {counter}</h3>
<button onClick={onClickEvent}>Click me</button>
</div>
);
render();
</script>
위 코드는 버튼을 클릭할 때, counter 변수가 버튼을 카운트하면서
카운트 수를 실시간으로 표출해주는 예제이다.
위 코드를 브라우저에서 확인해보면 Header 내부의 마지막 요소로 script가 추가된 것을 확인할 수 있다.
<script>
"use strict";
var root = document.getElementById('root');
var counter = 0;
var onClickEvent = function onClickEvent() {
counter = counter + 1;
render();
};
var render = function render() {
ReactDOM.render( /*#__PURE__*/React.createElement(Container, null), root);
};
var Container = function Container() {
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h3", null, "Total: ", counter), /*#__PURE__*/React.createElement("button", {
onClick: onClickEvent
}, "Click me"));
};
render();
</script>
이처럼 JSX를 활용하여 React element를 생성하고 babel을 통해 ReactJS가 이해할 수 있는 형태로 변환되는 것을 확인할 수 있다.
useState
React.js 어플 내에서 데이터를 보관하고 자동으로 리렌더링을 일으키는 방법 변수에 React.useState(); 를 담아서 찍어보면 배열을 하나 받는 것을 알 수 있다.
const root = document.getElementById('root');
const render = () => {
ReactDOM.render(<App />, root);
};
function App() {
const data = React.useState();
}
render();
//
여기서 중요한 것은 배열 내의 undefined 값은 ‘데이터’이고, 함수는 ‘데이터를 조작하는 함수’이다.
React.useState();내에 값을 주면 초기값으로 지정할 수 있다.
// 다음과 같이 1로 초기화할 수 있다.
const data = React.useState(1);
데이터를 조작하는 함수에 대해 알아보자.
// const data = React.useState(0);
// 기존에는 위처럼 data에 배열을 받아 썼지만, 구조 분해 할당(destructuring assignment)을 통해 각각의 변수에 선언 및 할당가능
// 참고: https://kyjky.github.io//JavaScript-26/
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
React.useState()를 사용하여 받은 배열의 두 번째 값인 데이터를 조작하는 함수는 배열의 첫 번째 값인 데이터를 조작할 수 있다.
위의 코드에서 함수 내부에 counter + 1를 인수로 전달하면, onClick이 실행될 때마다 counter + 1의 값 평가가 일어난 후, counter 값에 재할당된다.
기존에는 리랜더링을 하려면 ReactDOM.render()를 썼어야 됐지만, 데이터를 조작하는 함수 내부에는 리랜더링 기능을 포함하기 때문에 onClick이 실행되면 counter 변수가 재할당된 후, 리랜더링이 자동적으로 실행된다.
때문에 변수의 값(상태)이 조작될 때, 상태를 웹에 반영하기 위해 굳이 ReactDOM.render()를 다시 해줄 필요가 없다.
위 함수를 위와 같이 사용할 때, 해당 함수 외에 다른 예기치 않은 재할당에 의해 엉뚱한 데이터가 들어갈 수 있다.
이를 방지하고자 아래와 같이 수정한다.
const onClick = () => {
// setCounter(counter + 1);
setCounter((current) => counter + 1);
};
데이터 조작 함수에 함수를 추가하는 방식인데, 이 함수의 첫 번째 argument는 해당 데이터의 현재 값이다.
때문에 위와 같이 매개변수로 현재 상태의 데이터의 값을 받아서 재할당하면 더욱 안전하게 작동한다.