import "./App.css";
function App() {
const age = 0
const increaseAge = () => {
age = age+1;
console.log(age);
};
return (
<div className="App">
{age}
<button onClick={increaseAge}> Increase age</button>
</div>
);
}
export default App;
리액트에서도 js처럼 버튼을 만들어서 숫자를 올리고 싶다면 어떻게 하면 될까?
이렇게 코드를 써서 increaseAge 함수를 버튼에 연결해줬다고 생각했는데, 이상하게도 작동되지 않는다. 왜일까?
왜냐면 age를 우리가 const로 설정했기 때문이다.
그런데 우리가 그것을 let으로 바꿔줘도 화면에 표시된 0은 변하지 않는다.
그런데 이상하게도 콘솔에 찍히는 숫자는 계속 올라가고 있다...
왜냐면 변수는 변하고 있지만, 화면은 변하고 있지 않기 때문이다.
이게 무슨 말일까?
리액트는 처음 실행되면 App 컴포넌트를 한 번 렌더링 한다.
렌더링한다는 것은 이 App 컴포넌트에 따라 UI를 생성한다는 것이다.
그래서 처음에는 당연히 age가 0이라고 표시되고, 변수가 뭐라 변하든 리액트는 변수의 변화는 눈치채지 못한 채 컴포넌트 기준으로 0을 UI에 표시하고 있는 것이다.
그냥 JS에서는 document.get을 통해서 html로 표시되는 UI에 변수 변화를 가져올 수 있었겠지만, 리액트에서는 그 방법이 다르다. 바로 useState라는 hook을 사용하면 된다.
import {useState} from 'react'
hook는 리액트에서 사용하는 개념으로, use로 시작하는 일종의 함수이다.
useState는 state를 만들어서 사용하기 위해 쓰는 hook이다.
예를들어서 우리가 age라는 state를 만들고 이것을 변화시키는 함수를 만든다고 생각해보자.
const [age, setAge] = useState()
이것이 바로 useState의 구조이다. () 안에는 useState의 초깃값을 넣을 수 있다. age라는 변수를 만들어주고, age라는 변수를 변화시키는 setAge라는 함수와의 세트를 짝지어 준 것이다.
const [age, setAge] = useState(1);
const increaseAge = () => {
setAge(age+1);
};
이와 같이 코드를 작성하면 increaseAge 함수가 작동할 때마다 age가 setAge() 안에 설정된 값(1살 늘어나기)으로 변화할 것이다.
그 이유는 바로 state의 정체성이 설정된 변수가 변하면 리액트에게 알려주어서 다시 렌더링하도록 트리거가 되기 때문이다. 그러면서 새로 갱신된 state의 변수를 반영할 수 있다.
만약 내가 화면에 텍스트를 넣을 수 있는 input이 있고, 이 input에 들어가는 글자를 바로 화면에 state를 이용해서 띄우고 싶다면 어떻게 해야 할까?
const [inputValue, setInputValue] = useState("");
...
<div className="App">
<input type="text" onChange={} />
{inputValue}
</div>
이렇게만 하면 당연히 변화는 없다. 그래서 우리는 onChange를 이용해서 input에 변화가 생기면 event 전달을 통해 inputValue가 바뀔 수 있도록 해줄 것이다.
function App() {
const [inputValue, setInputValue] = useState("");
const handleInputChange = (event) => {
setInputValue(event.target.value);
};
return (
<div className="App">
<input type="text" onChange={handleInputChange} />
{inputValue}
</div>
);
}
이처럼 handleInputChange함수에서 event를 전달받아 input의 정보를 끌어오고, event.target.value로 현재 값을 가져와서 변화가 생길 때마다 화면에 반영해줄 수 있다.
function App() {
const [showText, setShowText] = useState(false);
return (
<div className="App">
<button> Show/Hide </button>
{showText === true && <h1>Hi this is text.</h1>}
</div>
);
}
이 코드에서는 showText라는 state를 가지고 boolean 값에 따라 h1태그로 쓰여진 글을 보여줄지 말지를 결정한다.
위의 버튼을 눌렀을 때 글자가 보이는지를 결정하려면 어떻게 하면 좋을까?
function App() {
const [showText, setShowText] = useState(false);
return (
<div className="App">
<button onClick={() => {setShowText(!showText)}}> Show/Hide </button>
{showText === true && <h1>Hi this is text.</h1>}
</div>
);
}
onClick 안에 익명 함수로 setShowText가 showText를 반대로 만듦으로써 버튼을 누를 때 현재 상태를 반전시켜 글씨를 보여주거나 숨길 수 있게 된다.
그러면 버튼을 누르면 이번엔 색깔을 바꾸려면 어떻게 해보면 좋을까?
이것도 마찬가지로, h1 태그 안에 바로 CSS 중 color를 바꾸도록 해서 onClick에 대해 색깔을 바꾸는 익명 함수를 추가해주면 된다.
당연히 이 때, h1태그 안에서 style, color를 textColor로 설정해주어야 state를 이용해서 색 변경을 적용시킬 수 있다.
function App() {
const [textColor, setTextColor] = useState("green");
return (
<div className="App">
<button
onClick={() => {
setTextColor("red");
}}
>
color change
</button>
<h1 style={{ color: textColor }}>Hi this is text.</h1>
</div>
);
}
만약 글씨가 빨강일 때 누르면 초록, 초록일 때 누르면 빨강으로 스위치 되기를 원하면 삼항연산자를 이용해서 조건에 따라 글자 색이 바뀌도록 익명함수를 써줄 수 있다.
function App() {
const [textColor, setTextColor] = useState("green");
return (
<div className="App">
<button
onClick={() => {
setTextColor(textColor === "green" ? "red" : "green");
}}
>
color change
</button>
<h1 style={{ color: textColor }}>Hi this is text.</h1>
</div>
);
}