일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- box-shadow
- className
- Grid
- css#cascading#display#block#inline
- grid-template-areas
- javascipt
- localStorage
- foreach()
- javascript
- grid-column-start
- prompt()
- React
- createElement
- gird-row-end
- border-style
- mongodb
- valuable
- grid-row-start
- package.json
- python #qqplot #qq-plot #code
- CSS
- confirm()
- classList
- collapsing-margins
- grid-column-end
- relative
- variables
- scope
- var
- react-hook-form
- Today
- Total
data life
[React] State 본문
⭐State ⭐
1️⃣ state를 쓰는 이유
2️⃣ useState()
3️⃣ state 불변성
4️⃣ state 다루기
1️⃣ state를 쓰는 이유
버튼 클릭시 ,+1 이 되도록 구현하는 카운터로 예시를 들어봄
/**App.js**/
function App(){
return (
<div className = "App">
<Counter />
</div>
)
}
export default App;
/**Counter.js**/
export default function Counter(){
let count = 0;
return(
<div>
<button onClick={()=>(count +=1)}>+1</button>Counter : {count}
</div>
);
➡️카운터 클릭 시, 변경되지 않는 것을 확인할 수 있다.
왜냐하면, 카운터는 단지 함수구문이기 때문에!
따라서, 함수 컴포넌트 내에서 상태를 관리해야하는 일이 필요하다.
🤔컴포넌트가 상태를 관리한다는 의미?
상태값을 변경할 수 있고 변경시 컴포넌트가 랜더링이 일어나게 할 수 있다는 것을 의미한다!
리액트에서는 hook함수라는 것을 통해 상태를 관리하는데
그 중 useState는 배열을 리턴하여 컴포넌트의 리렌더링을 발생시킨다.
2️⃣ useState()
//state (값), setState(변경 값)
const [state, setState] = useState();
/**Counter.js**/
export default function Counter(){
const [count, setCount] = useState(0);
return(
<div>
<button onClick={()=>setCount(count+1)}>+1</button>Counter : {count}
</div>
);
}
3️⃣ state 불변성
❓불변성 (immutable) 이란?
"변하지 않는 성질"
: 프로그래밍에서 불변성을 지킨다라는 의미는 메모리 영역 값을 직접적으로 변경하지 않는다는 뜻!
setState() => 컴포넌트의 re-rendering
만일, 불변성을 지키지 않고, 메모리 영역값을 직접 변경하면 리액트는 state가 변경되었다고 인식하지 못한다.
=> re-rendering을 발생시키지 않게됨
왜냐하면 리액트는 이전 state와 이후 state를 비교할 때, 얕은 비교(shallow Compare)를 하기 때문!!
💡얕은 비교에 대해 알아보자면,
이전, 자바스크립트에서 원시타입과 참조타입이 존재하는 것을 알 수 있었는데 원시타입은 불변성을 지니고 있어 변수에 원시 타입 값을 할당하면 메모리에 값 자체가 저장이 되고
반면, 참조 타입은 불변성을 가지고 있지 않아 변수에 참조 타입 값을 할당하면, 메모리 값이 담긴 주소가 저장이 된다.
4️⃣ state 다루기
원시타입의 state 부터 다뤄보도록 하자.
- +1 버튼 : 클릭 시, 값을 1씩 증가시킨다.
- Show and Hide 버튼 : 클릭 시, 나타나거나 사라지게 한다.
- Change Operator : + - * 중 랜덤하게 선택하여 카운터 계산에 적용한다.
/**Counter.js**/
export default function Counter(){
const [count, setCount] = useState(0);
const [show, setShow] = useState(true);
const operators = ["+", "-", "*"];
const [operator, setOperator] = useState(operators[0]);
return(
<div>
<button onClick={()=>{
let result;
if (operator === "+") result = count + 1;
if (operator === "-") result = count - 1;
if (operator === "*") result = count * 1;
setCount(result);
}}>{operator}1</button>
<button onClick={()=>setShow(!show)}>Show and Hide</button>
<button onClick={()=>{
const idx = Math.floor(Math.random() * operators.length);
setOperator(operators[idx]);
}}>Change Operator</button>
{ show && `Counter : ${count} `}
</div>
);
}
이번엔 참조타입의 state를 다뤄보도록 하자.
const [count, setCount] = useState(0);
const [show, setShow] = useState(true);
const [operator, setOperator] = useState(operators[0]);
⬇️
const [info, setInfo] = useState({
count : 0,
show : true,
operator : operators[0];
});
과 같이 object 형태로 변경해주도록 하자
return(
<div>
<button onClick={()=>{
let result;
if (info.operator === "+") result = count + 1;
if (info.operator === "-") result = count - 1;
if (info.operator === "*") result = count * 1;
setInfo(result);
}}>{info.operator}1</button>
<button onClick={()=>{
info.show = !info.show;
const newInfo = info;
setInfo(newInfo);
}}>Show&Hide</button>
<button onClick={()=>{
const idx = Math.floor(Math.random() * operators.length);
setInfo(info.operators[idx]);
}}>Change Operator</button>
{ info.show && `Counter : ${info.count} `}
</div>
);
}
객체로 변경된 만큼 아래 코드도 다음과 같이 변경해주었다.
그러나 랜더링이 되지 않는다.😥
<button onClick={()=>{
info.show = !info.show;
const newInfo = info;
setInfo(newInfo);
}}>Show&Hide</button>
앞서 말한 것처럼, 참조타입인 객체가 주소만을 복사했기 때문에 리액트는 객체값이 변경되었다는 것을 확인할 수 없게 된다. 그래서 위와 같은 코드로 작성하면 못 알아채는 것이었음
그렇기 때문에 새로운 객체를 setInfo()에 넣어주어야 한다.
=> 스프레드 구문을 이용해줌
<button onClick={()=>{
setInfo({...info, show : !info.show});
}}>Show&Hide</button>
다른 버튼들도 위와 같이 작성해주도록 하자.
<button onClick={()=>{
let result;
if (info.operator === "+") result = count + 1;
if (info.operator === "-") result = count - 1;
if (info.operator === "*") result = count * 1;
setInfo({...info, count : result});
}}>{info.operator}1</button>
<button onClick={()=>{
const idx = Math.floor(Math.random() * operators.length);
setInfo(...info, operator : operators[idx]);
}}>Change Operator</button>
배열(array)에서도 마찬가지이다.
✅잘못된 사용방법
arr[0] = "Hi"
const newArr = arr;
setArr(newArr)
✅올바른 사용방법
setArr([...arr, newItem])
setArr([arr.filter(arr=>{}))
'Front-end > React' 카테고리의 다른 글
[React] State 끌어올리기 (0) | 2023.03.29 |
---|---|
[React] State의 비동기적 업데이트 (0) | 2023.03.29 |
[React] 라이브러리 vs 프레임워크 (0) | 2023.03.24 |
[Project] React로 단위변환기 만들기 (0) | 2022.12.25 |
[React] React 기초 (0) | 2022.12.17 |