이 글은 노마드 코더님의 React 강의를 학습한 내용을 기반으로 작성합니다.
State Functions
setState 함수를 사용해 state 값을 변경하는 두 가지 방법이 존재한다.
1. setState()를 이용해 직접 원하는 값을 넣어준다. (setState(값))
2. 이전 값을 이용해 현재 값을 계산한다. (함수적 갱신)
: 함수의 첫 번째 인자 (argument)는 현재 값이다.
함수의 return값이 새로운 state값이 된다.
-> 두 가지 방법 중 두 번째 (= 함수적 갱신) 방식이 더 안전하다.
왜냐하면 함수적 갱신 방식으로 함수를 사용했을 때 React가 해당 current가 확실히 현재값임을 보장해주기 때문이다.
참고
React는 HTML과 비슷한 JSX 방식을 사용한다.
하지만 JSX 방식에서는 class와 for과 같은 요소들을 사용하지 못한다.
위 사진처럼 경고 메시지가 출력되는 것을 확인할 수 있다.
이러한 문제를 해결하기 위해 다음과 같이 작성해야 한다.
class -> className
for -> htmlFor
Inputs and State
단위 변환 (unit conversion) 예제
예제 #1
<!DOCTYPE html>
<html>
<head> </head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script 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");
let counter = 0;
function App() {
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">minutes</label>
<input id="miniutes" placeholder="Minutes" type="number" />
<label htmlFor="hours">hours</label>
<input id="hours" placeholder="Hours" type="number" />
</div>
);
}
ReactDOM.render(<App />, root); // App을 root 안에 랜더링
</script>
</html>
예제 #1 결과
React에서 input은 uncontrolled이다.
즉, input의 value를 통제할 수 없다.
예제 #2
<!DOCTYPE html>
<html>
<head> </head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script 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");
let counter = 0;
function App() {
const [minutes, setMinutes] = React.useState();
const onChange = (event) => {
console.log(event);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">minutes</label>
<input
value={minutes}
id="miniutes"
placeholder="Minutes"
type="number"
onChange={onChange}
/>
<label htmlFor="hours">hours</label>
<input id="hours" placeholder="Hours" type="number" />
</div>
);
}
ReactDOM.render(<App />, root); // App을 root 안에 랜더링
</script>
</html>
예제 #2 결과
event를 console.log()로 출력하면 SyntheticBaseEvent (합성 이벤트)가 출력된다.
여기서 원래의 event는 nativeEvent에 해당한다.
SyntheticBaseEvent 내부에 target이 존재하는데 이것은 이벤트가 발생한 input을 의미한다.
즉, input 요소의 값은 event.target.value로 설정한다.
예제 #3-1
<!DOCTYPE html>
<html>
<head> </head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script 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");
let counter = 0;
function App() {
const [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">minutes</label>
<input
value={minutes}
id="miniutes"
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>
);
}
ReactDOM.render(<App />, root); // App을 root 안에 랜더링
</script>
</html>
예제 #3-1 결과
input 요소의 값이 변할 때마다 onChange() 메서드가 실행되어 value값이 변경되는 것을 알 수 있다.
참고
input 요소의 onChange={onChange} 문장을 주석처리하면 input 요소에 값을 입력하더라도 변경되지 않고 계속해서 0을 유지한다.
왜냐하면 state의 초기값을 0으로 설정했기 때문이다.
즉, state의 값을 업데이트하기 위해서는 state, setState 모두 필요하다.
예제 #3-2
<!DOCTYPE html>
<html>
<head> </head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script 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() {
const [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
};
const reset = () => setMinutes(0);
return (
<div>
<h1 className="hi">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"
disabled
/>
</div>
<button onClick={reset}>Reset</button>
</div>
);
}
ReactDOM.render(<App />, root); // App을 root 안에 랜더링
</script>
</html>
예제 #3-2 결과
예제 #4 flip function
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/mvp.css" />
</head>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script 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() {
const [amount, setAmount] = React.useState(0);
const [inverted, setInverted] = React.useState(false);
const onChange = (event) => {
setAmount(event.target.value);
};
const reset = () => setAmount(0);
const onInvert = () => {
reset();
setInverted((current) => !current);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<div>
<label htmlFor="minutes">minutes</label>
<input
value={inverted ? amount * 60 : amount}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
disabled={inverted}
/>
</div>
<div>
<label htmlFor="hours">hours</label>
<input
value={inverted ? amount : Math.round(amount / 60)}
id="hours"
placeholder="Hours"
type="number"
disabled={!inverted}
onChange={onChange}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onInvert}>
{inverted ? "Turn back" : "Invert"}
</button>
</div>
);
}
ReactDOM.render(<App />, root); // App을 root 안에 랜더링
</script>
</html>
예제 #4 flip function 결과
'React > State' 카테고리의 다른 글
Final Practice and Recap (0) | 2022.07.27 |
---|---|
setState (0) | 2022.07.26 |