React JS는 웹사이트를 interactive하게 만든다.
이를 알아보기 위해, 클릭을 위한 버튼 하나와 클릭 수를 출력하는 텍스트로 이루어진 사이트를 작성한다.
<!DOCTYPE html>
<html>
<body>
<span>Total clicks: 0</span>
<button id="btn">Click me</button>
</body>
<script>
let counter = 0; //클릭 수를 세기 위해 counter 변수를 선언한다.
const button = document.getElementById("btn"); //btn id의 버튼을 가져온다.
const span = document.querySelector("span"); //span 태그를 가져온다.
function handleClick(){ //클릭 시 실행할 함수를 작성한다.
counter=counter+1 // counter 변수를 1 증가시킨다.
span.innerText = `Total clicks: ${counter}`; // span 태그를 변경한다.
}
button.addEventListener("click",handleClick) //click event를 감지한다.
</script>
</html>
코드 양이 많기 때문에, 이를 아래와 같이 개선할 수 있다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
}
return(
<div>
<h3>Total clicks : {counter}</h3>
<button onClick={onClick}>Click me!</button>
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
</html>
위의 코드를 도출하는 방법은 아래 단계를 따른다.
리액트를 import하기 위해 본 강의에서는 아래 두 개 링크를 사용했다.
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
리액트를 사용해 화면에 Hello, I'm a span. 이라는 텍스트를 띄우기 위해서는 아래와 같이 작성할 수 있다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div> <!--root 생성-->
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<!--React JS는 요소 생성을 돕는 라이브러리, React-DOM은 이를 body태그에 넣어준다.-->
<script>
const root = document.getElementById("root"); //root 가져오기
const span = React.createElement( //Element를 생성한다.
"span", //argument1. 해당 Element는 span이다. --> 오타 주의
{id: "sexy-span", style: { color: "red" }}, //argument2. property는 다음과 같다.
"Hello, I'm a span" //argument3. content
);
ReactDOM.render(span, root); //요소들을 React DOM을 사용해 span을 root에 렌더링 하기.
</script>
</html>
React의 기본 구조(sript->HTML)이 반영되어
아래는 console 창에 문구를 띄우는 텍스트와 버튼을 생성하는 코드이다.
각각 onMouseEnter와 onClick 이벤트에 해당하며, 다음과 같이 작성할수 있다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<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>
<script>
const root = document.getElementById("root");
const h3 = React.createElement(
"h3",
{onMouseEnter: () => console.log("im mouse")},
// 화살표 함수를 이용해 마우스를 가져다 대면 im mouse 출력한다.
"Hello, I'm a span"
);
const btn = React.createElement(
"button",
{onClick: () => console.log("im clicked"),
// 화살표 함수를 이용해 클릭하면 im clicked 출력한다.
style: {
backgroundColor: "tomato",
}},
"Click me!");
const container = React.createElement("div", null, [h3, btn]);
// 복수의 요소를 출력하기 위해 container 생성
ReactDOM.render(container, root);
</script>
</html>
이제 버튼 클릭에 필요한 이벤트를 추가할 수 있다.
그러나 여전히 createElement를 사용한다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<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>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
const Title = (
<h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
Hello, I'm a title!
</h3>
);
const Button = (
<button
style={{
backgroundColor: "tomato",
}}
onClick={() => console.log("im clicked")}
>
Click me!
</button>
);
const container = React.createElement("div", null, [Title, Button]);
ReactDOM.render(container, root);
</script>
</html>
위의 코드는 2번 문항과 완전히 동일하게 작동하지만, Babel을 통해 JSX(대충 JS->HTML) 코드를 사용할 수 있다.
container까지 변환하면 아래와 같은 형태가 된다.
<script type="text/babel">
const root = document.getElementById("root");
const Title = () => ( // 함수로 변환
<h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
Hello, I'm a title!
</h3>
);
const Button = () => ( // function+return
<button
style={{
backgroundColor: "tomato",
}}
onClick={() => console.log("im clicked")}
>
Click me!
</button>
);
const Container = ( //첫 글자를 대문자로
<div>
<Title /> //Title과 Button을 태그처럼 사용
<Button /> // *주의: 컴포넌트의 첫 글자는 대문자
</div>
);
ReactDOM.render(Container, root);
</script>
현재까지 배운 것으로 처음의 click counter를 만들면 아래와 같다.
<script type="text/babel">
const root = document.getElementById("root");
let counter = 0;
function countUp() { // a. counter의 값을 1 올려준다.
counter = counter + 1
render();
}
function render() { //b. 재렌더링
ReactDOM.render(<Container />, root);
}
const Container = () => (
<div>
<h3>Total clicks : {counter}</h3> //counter 값 대입
<button onClick={countUp}>Click me!</button>
// c. 버튼 클릭 이벤트
</div>
);
ReactDOM.render(<Container />, root); // d. 렌더링
</script>
b의 과정이 없으면 업데이트가 되지 않기 때문에, 값이 화면에 반영되지 않는다.
버튼을 누르면 c->a->b 순으로 재렌더링이 일어난다.
이때, vanilla JS와는 다르게 counter 값 자체만 업데이트됨을 알 수 있다.
보다시피, 렌더링 하는 것을 잊게 되면 문제가 생긴다. 이 과정이 번거롭기 때문에, 아래와 같이 다시 작성할 수 있다.
useState를 사용하면 렌더링을 편리하게 할 수 있는데, 과정은 아래와 같다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<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>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function App() {
const [counter, setCounter] = React.useState(0);
//countUp 대체, 배열->배열
const onClick = () => {
setCounter(counter + 1);
//modifier가 counter 값을 해당 값으로 바꾸고 렌더링
}
return(
<div>
<h3>Total clicks : {counter}</h3>
<button onClick={onClick}>Click me!</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
위의 코드도 제대로 기능하기는 하지만, 앞으로 있을 문제들을 미리 방지하기 위해 아래와 같이 작성할 수 있다.
<script type="text/babel">
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
//setCounter(counter+1);과 동일, 더 안전
}
return(
<div>
<h3>Total clicks : {counter}</h3>
<button onClick={onClick}>Click me!</button>
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
현재의 값을 바탕으로 다음 값을 설정할 때는 위와 같이 함수의 형식으로 작성한다.
여기까지가 Vanilla JS로 작성된 Click Counter를 React로 변환하는 과정이다.