바닐라 JS와 리액트 JS의 차이점을 알고 어떤 장단점이 있는지 확인해 본다.
| Vanilla JS의 경우 HTML → JS 순서
📍 Html 작성
📍 html 요소를 JS로 가져온다.
📍 event를 감지하고 데이터를 업데이트 한다.
📍 Html에도 데이터 업데이트를 반영한다.
React JS는 이와 반대로 JS에서 HTML 요소
를 컨트롤 한다.
📍 JS 작성 | React 환경 설정
📍 React를 이용, HTML요소 생성 및 삽입
📍 event를 감지하고 데이터를 업데이트 한다.
📍 Html에도 데이터 업데이트를 반영한다.
<!DOCTYPE html>
<html>
<body>
<span>Total clicks = 0</span>
<button id="btn">Click here</button>
</body>
<script>
let counter = 0;
const span = document.querySelector("span");
const button = document.getElementById("btn");
function handleClick() {
counter = counter += 1;
span.innerText = `Total clicks = ${counter}`;
}
button.addEventListener("click", handleClick);
</script>
</html>
❗️여기서 사용된 html 샘플 코드는 리액트의 원리를 보여주기 위한 방식으로 실전에서 사용하는 방식은 아님을 알아두자!
📍 JS 작성 | React 환경 설정 : 리액트 import
react : React JS가 element를 생성하고
eventLinstener를 더하는 것을 도와줌💖인터렉티브 파워!!
react-dom : React element들을 가져다 HTML로 바꿈
📍 React.createElement( a )로 HTML요소 생성
ReactDOM.render(a, root)로 HTML요소 삽입
⇒ root경로에 넣어줌 (*root가 될 부분은 html에 만들어 둬야함)
<<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script crossorigin src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script>
const root = document.getElementById("root");
const span = React.createElement(
"span", // 태그 요소
{ id: "sexy-span", style: {color: "red"} }, // 속성
"Hello I'm a span" // 텍스트
);
ReactDOM.render(span, root);
</script>
</html>
📍 event를 감지하고 데이터를 업데이트 한다.
React.createElement()로 html 요소를 생성하는 동시에
이벤트도 할당 가능!
<<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script crossorigin src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script crossorigin 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("mouse enter") },
"Hello I'm a span"
);
const btn = React.createElement(
"button",
{onClick: () => console.log("I'm click")},
"Click me"
);
const container = React.createElement("div", null, [h3, btn]);
ReactDOM.render(container, root);
</script>
</html>
❗️ on + event 를 속성값으로 작성하면 브라우저는 이것이 이벤트임을 인식함.
[브라우저 요소창에 노출되어지지 않음!]
이벤트 값 외의 속성을 작성하면 html 요소로 인식해 나타내어 준다.
<!DOCTYPE html>
...
const h3 = React.createElement(
"h3",
{
id: "title",
onMouseEnter: () => console.log("mouse enter"),
style: { backgroundColor: "tomato" },
},
"Hello I'm a span"
);
This funny syntax is neither a string nor HTML.
It is called JSX, and it is a syntax ectension to JavaScript. (JSX = JS를 확장한 문법!)
const element = <h1> Hello, world</h1>
CreateElement( )를 사용하지 않고 HTML처럼 요소를 생성할 수 있다!
const root = document.getElementById("root");
const Title = (
<h3
src=""
id="title"
onMouseEnter={() => console.log("mouse enter!")}
>
Hello, I'm a title
</h3>
);
const Btn = (
<button
style={{ backgroundColor: "toamto" }}
onClick={() => console.log("I'm click")}
>
Click me
</button>
;
But, JSX는 브라우저가 인식하지 못하므로 ‘Babel’을 설치하여 읽을 수 있는 문법으로 변환 시켜줘야함!
These two examples are identical :
const element = (
<h1 class="greeting">
Hello, world
</h1>
)
const element = React.createElement(
'h1',
{className:"greeting"},
'Hello, world'
)
❗️리액트:JSX 작성+Babel로 변환한 코드, 실무에서는 요런식으로 작성한다!
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script crossorigin src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script crossorigin 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 src="" id="title" onMouseEnter={() => console.log("mouse enter!")}>
Hello, I'm a title
</h3>
);
const Btn = (
<button
style={{ backgroundColor: "tomato" }}
onClick={() => console.log("I'm click")}
>
Click me
</button>
);
const container = React.createElement("div", null, [Title, Btn]);
ReactDOM.render(container, root);
</script>
</html>
❗️Babel이 JSX를 변환시켜서 브라우저가 읽을 수 있는 코드로 바꾸고 ⇒ <head>에 담아둠.
JSX(width Babel)로 HTML에 요소를 생성하고 랜더하는 방법을 알았다. 이 요소들을 포함하는 id=”root”
도 JSX 문법으로 변환해서 JSX를 품은 JSX를 만들어보자🙂 더 이상의 React.createElement( )는 NONO~~
> 아래의 게시글은 'React17' 버전을 기준으로 작성되었음.
현재 'React18' 버전과 차이가 있으니 유의할 것.
[old] 'React 17'
const container = document.getElementById('root');
React.render(, container);
[new]'React 18'
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render();
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
...
...JSX요소(컴포넌트)를 <div id="root">(컴포넌트)에 넣어봅시당 ...
...
const container = React.createElement("div", null, [Title, Btn]);
ReactDOM.render(container, root);
</script>
</html>
Btn()
이 아닌 <Btn />
으로 작성해야한다!<script type="text/babel">
const root = document.getElementById("root");
const Title = () => (
<h3
src=""
id="title"
onMouseEnter={() => console.log("mouse enter!")}
>
Hello, I'm a title
</h3>
);
const Btn = () => (
<button
style={{ backgroundColor: "tomato" }}
onClick={() => console.log("I'm click")}
>
Click me
</button>
);
const Container = () => (
<div>
<Title />
<Btn />
</div>
)
ReactDOM.render(<Container />, root);
</script>
✅ 주의할 점!!각 JSX로 만들어지는 요소들(=컴포넌트)의 이름은 `대문자`로 작성한다! (파스칼 케이스),
소문자로 작성하면 HTML 요소라고 인식해 버린다.
const Title=… // const Btn=… // const Container=…
아래의 게시글은 'React17버전'을 기준으로 작성되었음.
현재 'React18버전'과 차이가 있으니 유의할 것.
Date가 저장되는 곳 || React.useState()로 State 생성한다!!
<script type="text/babel">
const root = document.getElementById("root");
let counter = 0 //카운터 초기화
function countUp() { //카운트업 함수
counter = counter + 1 //카운터 +1
render() //UI에 re랜더
}
function render() {
ReactDOM.render(<Container />, root);
}
function Container() {
return (
<div>
<h3> Total clicks : {counter}</h3> //UI에 최초 랜더 시 { 0 }
<button onClick={countUp}> Click me</button>
</div> //이벤트 리스너가 countUp 함수 호출
)
}
render()
</script> //UI에 최초 랜더
'알아두기 ✨ 동작순서'
1. 카운트업() 읽음 → 랜더() 읽음 → <리액트 요소> 읽음 → 랜더( ) `UI에 반영`
2. 카운트업() 동작: countUp+1, 랜더() → <리액트 요소>:{counter+1}반응 → 랜더():`UI에 반영`
modifier함수를 이용해서 컴포넌트의 state를 바꾼다!
( React.js로 data를 담고 업데이트 하는 법! )
바닐라 JS는 데이터 업데이트 시 변경사항이 없는 관련 태그들도 다 동기화 작동.
리액트 JS는 데이터 업데이트 시 변경되는 데이터만 업데이트 됨! (달라진 부분만 동기화 됨) ⇒ 인터렉티브한 어플을 만들 수 있음
이게 가능한 이유는 리액트 JS에서 modifier( )함수를 이용해서 컴포넌트의 state를 바뀌면 컴포넌트가 자동으로 재생성 되기 때문이다!
const [stat, setstate ] = React.useState('state 초기값')
'※ setState의 결과는 array임'
페이지 상단부 예문과 같이 불편한 방식 [수동 리액트]의 작성이다.
'State & setState'로 [자동으로 리랜더]가 되는 최고의 방식을 배워보자!!
활용
⇒ React.js어플 내에서 데이터를 보관
목적
⇒ render()를 반복해서 작성 X, 자동으로 리랜더
구조분해 할당으로 React.useState()
배열 형태를 깔끔하게 정리하자!
function App() {// [초기값, 수식어] 0번째 요소인 초기값
const [counter, modifier] = React.useState(0); //구조분해 할당
return (
<div>
<h3> Total clicks : {counter}</h3>
<button> Click me</button>
</div>
);
=====================================================
'구조분해 할당?'
const food = [”tomato”, ”potato”]
//1
const toamto = food[0]
const potato = food[1]
//2
const [toamto, potato] = food
☑️ modifier의 필요성
React.useState()
배열에는 일반적으로 데이터명과 함수명을[A, setA]
방식으로 작성한다.
ex)[counter, setCounter]
.
counter
에 어떤 값을 부여하면setCounter 함수
는 그 값으로 업데이트하고리랜더링
을 일으킴<script type="text/babel"> const root = document.getElementById("root"); ---------------------- 리액트 JSX ------------------------- function App() { let [counter, modifier] = React.useState(0); const onClick = () => { modifier(counter +1) } ------------------------- 컴포넌트 ---------------------------- return ( <div> <h3> Total clicks : {counter}</h3> <button onClick = {onClick}> Click me</button> </div> ) } --------------------------- 랜더 --------------------------// ReactDOM.render(<App />, root); </script>
counter
라는 데이터를 받음
return()
에 그 데이터를 담고 있음 (return( ) 은 사용자가 보게될 컴포넌트)- 버튼이 클릭되면 (counter값을 바꿔줄)
onClick()함수 호출 -> setCounter() 실행
- counter의 새로운 값을 가지고
counter() 함수
를 호출- 그 새로운 값은
setCounter(counter + 1)
에 써준 counter + 1
바닐라 JS와 리액트 JS의 코드를 비교해보자. (버튼 클릭시 카운터 증가)
📍바닐라 JS 작성 방식
<!DOCTYPE html>
<html>
<body>
<span>Total clicks = 0</span>
<button id="btn">Click here</button>
</body>
<script>
let counter = 0;
const span = document.querySelector("span");
const button = document.getElementById("btn");
function handleClick() {
counter = counter += 1;
span.innerText = `Total clicks = ${counter}`;
}
button.addEventListener("click", handleClick);
</script>
</html>
📍리액트 JS 작성 방식
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function App() {
let [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter +1)
}
return (
<div>
<h3> Total clicks : {counter}</h3>
<button onClick = {onClick}> Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
'바닐라 JS 코드 → 버튼클릭 카운팅 이벤트'