state는 기본적으로 data가 저장되는 공간이다. 일단 state에 대해 설명하기 전에
우리가 전에 만들었던 vanilaJS를 reactJS로 구현해보려고한다.
counter라는 변수를만들고 click버튼을 누르면 숫자가 하나씩 증가하는 기능을 만들었다. 하지만 counter는 잘 늘어가긴하지만 아무도 UI를 새로고침해주지 않아 그대로이다.
처음에!!! 페이지가 로드 되었을 때 (counter = 0일때) render를 해주는게 전부이다. 그 이후 리렌더링을 하지않고있다.
그럼 단순히 onclick을 했을 때 rendering시켜주면 counter값이 변경될 것이다.
하지만 이게 최고의 방법도 아닐뿐더러 더 쉬운 방법이 존재한다.
이 방법은 우리가 값을 바꿀때마다 다시 렌더링하는걸 잊어서는 안된다.
vanilaJS에서는 값이 바뀔때 body, span값이 업데이트 되는 반면
reactJS에서는 그 '값'만 업데이트 된다. 이 점도 reactJS가 좋은 점 중 하나이다.
(Container자체를 render했지만 {counter}만 바뀜)
지금부터는 React.js 어플 내에서 데이터를 보관하고 자동으로 리렌더링을 일으킬 수 있는 최고의 방법을 배워보려고 한다. 계속 리렌더링을 직접 불러올 필요가 없다.
여기서 useState()를 사용해보려고한다.
useState를 호출하고 그걸 콘솔에 찍어보자
배열안에 2개의 요소가 들어있고 첫 번째는 undefined, 두 번째는 함수가 들어있다.
두 번째 요소인 함수로 첫번째 요소의 값을 바꿀 수 있다.
그리고 처음useState()안에 값을 넣어주면 (배열 객체 상관 x) 그 값이 첫 번째 요소의 값으로 초기화 된다.
여기 이 두요소가 만나서 우리가 전에 onClick에 넣어주었던 함수의 역할을 대신하고 있다.
ES6문법을 사용하여 손쉽게 변수에 집어 넣어보자
const [state, setState ] = React.useState(0); 이렇게 하면 되지만
아래와 같이도 가능하다. 어떤 것이 편한지는 본인 선택에 맡기겠다.
const data = React.useState(0);
const state = data[0]
const setState = data[1]
counter를 직접 바꾸면 즉 counter = counter + 1하면 값은 바뀌긴하는데 리렌더링이 이루어지지 않는다.
그럼 전과 같이 렌더링 함수를 또 호출해줘야하는데 그럼 의미가 없지않나?
이때 우리가 setCounter를 사용해야 한다. setCounter(인자)를 해주면
인자의 값을 counter로 업데이트하고 리렌더링을 일으킨다.
즉 setCounter(counter + 1)은
counter = counter + 1
ReactDOM.render(<App/>,root)를 해주는 것이다. 얼마나 간단히 전에 했던 vanilaJS를 대체할 수 있는지 확인할 수 있다. 그리고 오로지 바뀐 부분(counter)만 html에서 고친다.
다시한번 말하면 setCounter함수를 이용해서 count를 바꾸면 이 컴포넌트App()가 재생성되고 return도 한번 더 실행 되지만 이벤엔 새로운 값을 가지고 실행된다. state가 바뀌면 리렌더링이 일어난다. React는 똑똑해서 컴포넌트가 리렌터링될 때 두 번째 이벤트리스너가 등록되거나 html을 다시만드는게 아니라 state부분만 바뀐다.
이렇게 저번 글에서 만든 vanilaJS와 똑같은 기능을 간편하게 React로 만들어보았다.
HTML요소를 생성하거나 찾을 필요도 없고 ( JSX를통해 간편히 만듦 ) 이벤트 리스터를 더해줄 필요도 없고 (JSX안에 on속성으로 대체) UI를 업데이트해줄 필요도 없다(state에 값을 집어넣고 setState()를해주면 리렌더링이 일어남)
state에 대해 좀더 알아보자
stateFunction
setState(state + 1)를 사용할 경우 나는 1만더하려고 했는데 이 전에 state값이 바뀐 경우라면 기댓값과 다른 값이 나올 수도 있다. 따라서 함수를이용해서 '현재'의 값을 사용하는 방법을 배워보자
저 함수가 뭘 return을하든 이제 저 값이 state값으로 바뀐다. 아래방법도 똑같은 결과를 내긴하는데 위의 방법이 좀 더 안전하다.
왜냐면 확실한 현재 값이라는 걸 보장해주기 때문이다.
간단한 converter를 한번 만들어 보겠다.
input에 hours을 적으면 minute으로 바꿔주고 역도 성립한다.
kilometer를 적으면 mile로 바꿔주고 역도 성립하는 converter를 만들어 보려고한다.
JSX는 HTML과 비슷하지만 다른 점 몇가지 기억할 게 있다. <lable for class> 에서 for와 class는 react에서는 사용하면 안된다.html과 비슷해보여도 다르기 때문이다. 따라서 htmlFor과 className으로 대체해주어야 한다.
각 컴포넌트를 만들고 App에 집어넣으려고 한다.
먼저 flip과 amount의 state를 만들어주고 3개의 함수를 만들었다.
먼저 input에 숫자가 들어왔을때 숫자가 아니면 리턴하고 숫자면 그 숫자를 amount에 넣어주는 함수
그리고 flip을 클릭하면 hours->miles / miles->hours 로 바뀌는 함수
마지막으로 amount state를 0으로 바꿔주는 함수
이렇게 3가지이다.
MVP.css를 사용하여 간단한 css를 입혀보았다.
위와 같은 화면이다. flip에 boolean값을 주어 false일 때와 true일 때의 각 단위들이 작동하도록 삼항연산자를 사용하였다. 그리고 스위치 버튼처럼 disabled= {!flip}을 주어 read-only를 만들어 주었다.
위와 마찬가지로
KtoM또한 만들어주고
App안에 넣어주었다. select를 만들고 선택한 value (-1, 0, 1)등을 선택했을 때 setValue를 통해 리렌더링을 시켜주는 방식으로 구현하였다. 삼항연산자를 통해 value의 값에따라 컴포넌트를 출력하는 기능을 만들었다.