버튼을 누를 때마다 올라가는 counter 수와 같은 바뀔 데이터를 어떻게 담아야 할까?
컴포넌트는 한번만 렌더링이 되기 때문에 counter 변수의 값은 바뀌어도 UI의 counter은 바뀌지 않는다.
그렇다면 어떻게 할 수 있을까?
직접 리렌더링 시켜주는 방법 ( 실제로 쓰진 않고 단지 원리를 이해하기 위함 )
이 방법은 실제로 사용하지는 않고 단지 원리를 이해하기 위함이다.
이 방법에서는 UI를 변경해주기 위해서 우리가 만든 container 컴포넌트를 counter 수가 바뀔 때마다 리렌더링 시켜준다.
<script type="text/babel">
const root = document.getElementById("root");
let counter = 0;
function countUp() {
counter = counter + 1;
render();
}
function render() {
ReactDOM.render(<Container />, root);
}
function Container = () => (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
render();
</script>
이때 다시 렌더링 하더라도 리액트가 알아서 바뀐부분만 리렌더링 시켜준다.
리액트JS는 바뀐 부분만 리렌더링 해주기 때문에 효율적이다.
리액트 JS의 렌더트리는 단계가 최적화 되어있다.
바닐라js는 노드 정보가 바뀔 때마다 노드 트리를 처음부터 다시 생성해야하는 반면 리액트는 가상 돔을 써서 우리 시야에 보이는 부분만 수정해서 보여주고 모든 업데이트가 끝나면 일괄로 합쳐서 실제 돔에 던져준다.
React앱 내에서 데이터를 관리하고 자동으로 리렌더링 시켜주는 방법
리액트에서는 바뀌는 값을 state로 설정하고 함수를 통해서 관리할 수 있다.
<script type="text/babel">
const root = document.getElementById("root");
function App() {
// [데이터, 데이터를 바꾸는 함수] , 초깃값은 0으로 설정한다.
const [counter, setCounter] = React.useState(0);
const onClick = () => {
//setCounter은 값을 업데이트 하고 자동으로 리렌더링 시킨다
setCounter(counter + 1);
};
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
counter 변수를 컴포넌트에 연결해서 변수에 데이터를 담은 다음 setCounter을 통해서 해당 변수에 담긴 값을 바꾼다.
state 계산 방법
1. 값을 직접 할당
setState(state + 1)
2. 함수를 할당
setState( (current) => current + 1 )
현재 값과는 전혀 상관없는 값을 새롭게 할당하고 싶을 때는 방법1을 쓰고
현재 값을 기반으로 다음 state를 계산하고 싶을 때는 방법2를 쓰는 게 더 적합하다.
setState함수를 한번에 여러번 호출할 경우 방법1의 경우에는 값이 1만 증가하는데 방법2는 함수를 호출한 횟수만큼 증가한다.
State 변환 실습 : 시간 단위 변환기
<script type="text/babel">
const root = document.getElementById("root");
//시간 단위 변환 기능
function MinutesToHours() {
const [amount, setAmount] = React.useState();
const [flipped, setFlipped] = React.useState(false);
const onChange = (event) => {
setAmount(event.target.value); //event.target.value로 input에 입력되는 값을 알 수 있다.
};
const reset = () => setAmount(0);
const onFlip = () => {
reset();
setFlipped((current) => !current);
};
return (
<div>
<div>
<label htmlFor="minutes">Minutes</label>
<input
value={flipped ? amount * 60 : amount}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
disabled={flipped === true}
></input>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
value={flipped ? amount : Math.round(amount / 60)}
id="hours"
placeholder="Hours"
type="number"
onChange={onChange}
disabled={flipped === false}
></input>
</div>
<div>
<button onClick={reset}>Reset</button>
<button onClick={onFlip}>Flip</button>
</div>
</div>
);
}
//거리 단위 변환 기능
function KmToMiles() {
return <h3> KM 2 M</h3>;
}
//변환기
function App() {
const [index, setIndex] = React.useState("xx");
const onSelect = (event) => {
setIndex(event.target.value);
};
return (
<div>
<h1>Super Converter</h1>
<select value={index} onChange={onSelect}>
<option value="xx">Select your units</option>
<option value="0"> Minutes & Hours </option>
<option value="1"> Km & Miles </option>
</select>
<hr />
{index === "0" ? <MinutesToHours /> : null}
{index === "1" ? <KmToMiles /> : null}
</div>
);
}
ReactDOM.render(<App />, root);
</script>
리액트에서는 js 문법 중 태그의 속성인 for 대신 htmlFor을 사용하고 class 대신 className을 사용한다.
event를 들어주는 함수 하나 event가 발생했을 때 값을 업데이트 해주는 함수 하나해서 둘 다 필요하다.
'Tech > ReactJS' 카테고리의 다른 글
[React 기초] Effects (0) | 2022.05.23 |
---|---|
[React 기초] Props (0) | 2022.05.20 |
[ReactJS 기초] VanillaJS와 ReactJS 비교 (0) | 2022.05.17 |
[React] 그래프 데이터베이스 (0) | 2021.07.16 |
[React] 액션과 리듀서 (0) | 2021.07.16 |