[영화 웹] #3. STATE

#3.0 Understanding State
작동순서
1. Container 컴포넌트를 root에 먼저 rendering 한다
2. btn 의 Event가 발생하면 countUp함수가 실행된다
3. countUp함수는 counter 변수가 update되고 Rerendering시킨다.
Rerendering의 장점은 Data가 바뀐 부분만 적용된다는 것이다.
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script 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.querySelector('#root');
let counter = 0;
function countUp() {
counter = counter + 1;
reRender(); //위에 값이 바뀌고 여기서 바뀐 부분만 다시 랜더링 해주세요의 뜻
}
const Container = () => (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
function reRender() { // 랜더링을 담은 함수
ReactDOM.render(<Container />, root);
}
reRender(); //처음 랜더링 시켜줌.
</script>
</body>
[React 렌더링을 알아보자 1편]React의 특성
React가 어떻게 돌아가는지 알아가보기 전에 혹시 Javascript가 어떻게 돌아가시는지 모르고 계시다면 여기로 가셔서 먼저 학습하고 돌아와주세요.React는 자바스크립트 라이브러리의 하나로서 사용
velog.io
#3.1 setState part One
위 예제의 counter 변수, countUp함수를 아우르는 React의 useState함수가 있다.
const [state, setState] = useState(initialState);
useState는 상태저장변수, 변수 업데이트 함수를 Return한다.
const root = document.querySelector('#root');
function App() {
const [counter, modifier] = React.useState(0);
console.log(counter, modifier);
return (
<div>
<h3>Total clicks: {counter}</h3>
<button>Click me</button>
</div>
);
};
ReactDOM.render(<App />, root);
https://devdocs.io/react/hooks-reference#usestate
DevDocs
devdocs.io
#3.2 setState part Two
React.useState 함수는
modifier 함수를 이용해서 데이터 값을 바꾸게 되면,
그 값을 가진 컴포넌트(App)전체를 재랜더링 하게된다.
결국, return안에 있는 컴포넌트는 '실제로 바뀌는 값'만 판단해서 불필요한 리렌더링을 제외한 채로 재랜더링한다
Q. useState함수를 할당 받을때 let을 안쓰고 const를 쓰는이유?
counter는 const이지만 객체를 참조하고 있기때문에 재할당불가로,
참조하고 있는 객체의 주소는 절대 변경이 불가능하지만
그 객체는 변경이 가능해서 counter가 변경이 가능한 것처럼 보이는 시각적 효과가 생긴다. (배열은 객체다.)
const root = document.querySelector('#root');
function App() {
const [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);
#3.4 State Functions
state를 세팅하는 데는 2가지 방법이 있다.
const [state, setState] = React.useState(100);
1) 직접 할당 : setState(state +1)
2) 함수를 할당 : setState(state => state +1)
- 함수의 첫번째 인자는 현재 state이다
- 이 state는 자동으로 현재 state값을 호출시켜준다.
- state에 100이 입력된다.
현재 state랑 관련이 없는 값을 새로운 state로 하고싶은 경우에는 (1),
현재 state에 조금의 변화를 주어서 새로운 state를 주고 싶은 경우에는 (2)
#3.5 Inputs and State
JSX는 class 혹은 for 과 같이 JavaScript에서 이미 선점된 문법 용어를 사용하지 못한다.
그래서 class는 className으로 for은 htmlFor로 바꿔야한다.
<script type="text/babel">
const root = document.querySelector('#root');
function App() {
const [minutes, setMinutes] = React.useState();
const onChange = (event) => {
setMinutes(event.target.value);
};
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlFor="minutes">Minutes</label>
<input
value={minutes}
id="minutes"
placehoder="Minutes"
type="number"
onChange={onChange}
/>
<h4>You want to convert: {minutes}</h4>
<label htmlFor="hours">Hours</label>
<input id="hours" placehoder="Hours" type="number" />
</div>
);
};
ReactDOM.render(<App />, root);
</script>
#3.6 State Practice part One (분 -> 시 변환)
시간 컨버터는 2가지가 필요하다
1. event를 발생하는 함수( 데이터 업데이트 역할 )
2. 업데이트된 값을 보여주는 요소 (UI에 보여주는 역할)
<script type="text/babel">
const root = document.querySelector('#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} //UI로 값을 보여주는 역할
id="minutes"
placehoder="Minutes"
type="number"
onChange={onChange} //데이터를 업데이트 해주는 역할
/>
</div>
<div>
<h4>You want to convert: {minutes}</h4>
<label htmlFor="hours">Hours</label>
<input
value={Math.round(minutes / 60)}
id="hours"
placehoder="Hours"
type="number"
/>
</div>
<button onClick={reset}>Reset</button>
</div>
);
};
ReactDOM.render(<App />, root);
</script>
#3.7 State Practice part Two (시 <-> 분 변환)
onFilp 함수는 flipped의 값을 true <-> false로 바꾸기 위한 용도로 쓴다.
flip될때마다 amount값도 0으로 초기화 시켜준다.
flipped(T or F)값으로 minute과 hour의 input disalbed값에 대입 시켜서 Toggle처럼 쓸 수 있다.
만약 flipped 값이 false 이면
hour의 input Tag의 value 값을 삼항연산자를 이용해서 값을 구한다.
value = { flipped ? amount : Math.round(amount / 60) }
flipped 값이 true 이면
minute의 inputTag value값은
value = ( flipped ? amount * 60 : amount }
<script type="text/babel">
const root = document.querySelector('#root');
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); //true < - > false
}
return (
<div>
<h1 className="hi">Super Converter</h1>
<div>
<label htmlFor="minutes">Minutes</label>
<input
value={flipped ? amount * 60 : amount} //UI로 값을 보여주는 역할
id="minutes"
placehoder="Minutes"
type="number"
onChange={onChange} //데이터를 업데이트 해주는 역할
disabled={flipped === true}
/>
</div>
<div>
<h4>You want to convert: {amount}</h4>
<label htmlFor="hours">Hours</label>
<input
value={flipped ? amount : Math.round(amount / 60)}
id="hours"
placehoder="Hours"
type="number"
onChange={onChange}
disabled={flipped === false}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onFlip}>{flipped ? 'Flip: T' : 'Flip: F'}</button>
</div>
);
};
ReactDOM.render(<App />, root);
</script>
실행코드