state란?
: 현재 상태
const[state,setState] = useState(초기값);
state= 현재 상태값,
setState = state를 변경하고 싶을때 쓰는 변수
이때, 저 변수명은 우리의 입맛에 맞게 바꿀 수 있다
ex> const [time,setTime] = useState(5);
우선, 함수형 컴포넌트로 적용해보자!
function App() {
return (
<div>
<span>현재 시각: 1시</span> //하드코딩
<button>Update</button>
</div>
);
}
export default App;
현재 시각을 state에 담아 update 버튼을 누르면 자동증가되게 해보자.
import { useState } from "react";
function App() {
const [time, setTime] = useState(1);
const handleClick=() =>{
setTime(time+1);
};
return (
<div>
<span>현재 시각: {time}시</span>
<button onClick={handleClick}>Update</button>
</div>
);
}
먼저 import해주고, useState 개념을 적용하면 이제 위처럼 하드코딩을 하는 것이 아니라 time에 들어있는 초기값 1이 들어오게 되는 것이다.
실행시켜보면 잘 작동되는 걸 볼 수 있다.
이렇게 setTime 함수를 통해 state를 업데이트해 다시 렌더링이 되는 것이다!
실제 실행시켜보면 25시,26시,---35시까지 쭉쭉 올라가니까 실제 시계처럼 보이게 하려면
const handleClick = () => {
let newTime;
if (time >= 12) {
newTime = 1;
} else {
newTime = time + 1;
}
setTime(newTime);
};
이렇게 바꿔주면 된다!
또 실습을 해보자
function App(){
const [names,setName] = useState(['홍길동', '김민수']);
return(
<div>
<input type="text"/>
<button>upload</button>
{names.map((name,idx) =>{
return <p key={idx}>{name}</p>
})}
</div>
react에선 map함수를 통해 element를 출력하려면 key값이 있어야 하기에 배열의 index값을 줌.
이젠 onChange로 input칸에 내용을 입력하면 변경내용을 감지할 수 있게 설정해보자
<input type="text" value={input} onChange={handleInputChange}/>
handleInputChange라는 함수를 생성함.
const handleInputChange= (e)=>{
setInput(e.target.value);
};
setInput을 통해서 inputState를 업데이트 시켜줄거임.
그럼 Inputstate가 사용자의 입력을 받을때마다 어떻게 업데이트 되는지 콘솔로 확인해보자!
더나아가서 만약 '아무개'를 입력해서 목록에 더 추가하고 싶어서
const handleUpload=()=>{
setNames(["홍길동", "김민수","아무개"])
}
라고 작성하면 맞을까??
이렇게 전 state와 새로운 state가 밀접하게 연관되어 있을 경우에는 인자안에 값을 바로 넣는게 아니라, 콜백함수를 전달해주는 것이다.
const handleUpload=()=>{
setNames((prevState)=>{
return [input, ...prevState];
})
}
인자에는 이전 state인 prevState가 들어가게 된다.
배열에 첫번째에는 input값,두번째엔 이전state값이 return됨!
근데 이렇게 upload할때마다 이전 값이 계속해서 렌더링 되면
무거운 로직을 돌릴때 시간도 많이 걸리고 메모리 낭비도 심할 것이다..
예시로
const heavyWork = () => {
console.log("무거운 작업");
return ["홍길동"];
};
function App() {
const [names, setNames] = useState(heavyWork());
이렇게 무거운 작업이라는 함수를 만들어서 보면
매번 호출되버린다.
증말 비효율적!!!!
그래서 딱 맨 처음에만 랜더링되게 해야함!
인자값에 바로 넣어주는 것이 아니라 또 콜백을 넣는 것이다.
const [names,setNames] = useState(()=>{
return heavyWork();
});
이렇게 무거운 작업을 할때에는 맨 처음에만 호출되게 콜백함수로 return을 작성해 줘야 한다!