React.js의 state는 데이터가 저장되는 곳이다. 우리가 만들고 있는 클릭 횟수를 count해서 화면에 출력하는 프로그램에서 이 counter(변화하는 data)를 state를 활용해 만들 수 있다.
<script type="text/babel">
const root = document.getElementById("root");
let counter = 0;
function countUp(){
counter = counter+1;
render(); // 데이터가 변화할 때마다 리렌더링
}
function render(){
ReactDOM.render(<Container />, root);
}
const Container = () => (
<div>
// JSX에서 변수는 `${}`필요없이 아래와 같이 {변수명} 만으로 사용 가능하다
<h3>Total clicks : {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
render();
</script>
아주 중요한 점! React.js는 이전에 렌더링된 component와 다음에 렌더링될 component를 보고 다른 부분만을 변경한다.
여러 가지 요소들을 리렌더링하더라도, 전체가 새로 생성되는 것이 아니라 바뀐 부분만이 생성된다. 이것이 react를 사용하는 가장 큰 이유다.
위의 코드는 데이터가 바뀔 때마다 rerendering하는 것을 잊지 말아야 한다. 다음 영상에서는 rerendering을 하는 좋은 방법을 알아볼 것이다.
이번 장에서는 React.js 어플 내에서 데이터를 보관하고 자동으로 rerendering을 일으키는 방법을 배울 것이다.
const data = React.useState(0);
-> data는 [0, f]. 우리가 담으려는 data값과 그 값을 변화시키기 위한 함수를 하나 갖는 배열이 된다.
const food = ["tomato", "potato"]
// 배열의 요소에 이름 할당
const [myFavFood, mySecondFavFood] = food;
// 이렇게 하는 것과 동일하다
// const myFavFood = food[0];
// const mySecondFavFood = food[1];
// const data = React.useState(0);
// 이렇게 쓸 수 있다.
const [counter, modifier] = React.useState(0);
앞으로 어떻게 modifier를 이용해 counter의 값을 바꿔줄지 배워보자!
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
위와 같이 state를 이용하면 setCounter()안의 값으로 data가 변한 후 렌더링까지 자동으로 해준다!
내용 정리.
modify 함수를 통해 state가 변화하면 컴포넌트가 새로 생성된다. 데이터가 바뀔 때마다 컴포넌트를 리렌더링하고 UI를 refresh 하는 것이 React.js가 제공하는 가장 중점적인 부분이다.
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
이전 단계의 state를 이용해 현재 state를 바꾸는(기존의 counter값을 이용해 새로운 counter값을 계산하는) 방식은, 어딘가에서 counter가 변경되어서 생각했던 값이 아닐 수 있다는 점 때문에 좋지 않다. state를 바꾸는 다른 방법을 알아보자.
// setCounter(counter + 1);
setCounter(current => current+1);
위의 두 줄은 같은 작업을 하지만, 아래와 같이 쓰는 것이 더 안전하다. 리액트가 이 current가 확실히 현재 값이라는 것을 보장하기 때문이다.
<div>
<h1>Super Converter</h1>
<label for="minutes">Minutes</label>
<input id="minutes" placeholder="Minutes" type="number" />
<label for="hours">Hours</label>
<input id="hours" placeholder="Hours" type="number" />
</div>
label 태그의 글씨를 입력하면 각각 연결된 input이 선택된다. 위는 HTML의 방식으로 label과 input을 연결(for를 사용)하고 있는데, JSX에서는 틀린 문법이다. JSX는 HTML문법과 유사하지만 몇 가지 주의해야 할 점이 있다. class와 for 등은 이미 javascript의 예약어이기 때문에, class 대신 className, for 대신 htmlFor 라고 써 줘야 한다.
function App(){
const [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
}
return (
<div>
<h1>Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input
value={minutes}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
/>
<h4>You want to convert {minutes}</h4>
<label htmlFor="hours">Hours</label>
<input id="hours" placeholder="Hours" type="number" />
</div>
);
};
state를 이용해서, input의 value를 state에 연결하여 사용자가 입력한 minutes값을 받아오는것까지 만들었다.
function App(){
const [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
}
const reset = () => setMinutes(0);
return (
<div>
<h1>Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
value={minutes}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
/>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
value={Math.round(minutes/60)}
id="hours"
placeholder="Hours"
type="number"
/>
</div>
<button onClick={reset}>Reset</button>
</div>
);
};
hours의 input value에도 state를 연결하여 입력한 분을 시간으로 바꿔주는 프로그램을 만들었다. 모든것을 0으로 돌려주는 reset 버튼도 추가!
다음 절에서는 disabled와 flip을 통해 시간을 입력하면 분으로 바꾸는 것도 가능하도록 해 보자.
function App(){
const [amount, setAmount] = React.useState(0);
const [flipped, setFlipped] = React.useState(false);
const onChange = (event) => {
setAmount(event.target.value);
}
const reset = () => setAmount(0);
const onFlip = () => {
reset();
setFlipped((current) => !current);
}
return (
<div>
<h1>Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
value={flipped? amount*60 : amount}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
disabled={flipped}
/>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
value={flipped ? amount : Math.round(amount/60)}
id="hours"
placeholder="Hours"
type="number"
disabled={!flipped}
onChange={onChange}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onFlip}>Flip</button>
</div>
);
};
flip 버튼을 이용해 disabled의 상태를 뒤집으며 버튼을 클릭할 때 마다 hours와 minutes input이 번갈아 유효하게 한다. 삼항연산자를 이용하여 각 경우에 알맞은 단위 변환이 가능하도록 한다.
복습! 내용정리!
function App(){
const [index, setIndex] = React.useState("0");
const onSelect = (event) => {
setIndex(event.target.value);
}
return (
<div>
<h1>Super Converter</h1>
<select value={index} onChange={onSelect}>
<option value="0">Minutes & Hours</option>
<option value="1">Km & Miles</option>
</select>
<hr />
{index === "0" ? <MinutesToHours /> : null}
{index === "1" ? <KmToMiles /> : null}
</div>
);
};
이전까지 만들었던 기능은 MinutesToHours 라는 이름의 함수로 바꾸고, KmToMiles 변환 기능을 갖는 함수를 또 만든 후 select tag를 이용하여 둘 중 하나를 선택해서 화면에 표시할 수 있도록 만들었다.