State : 어떤 사물의 모양이나 형편, 계속해서 변화하는 값
리액트의 컴포넌트들도 상태를 갖는다. 여러 개 가질 수 있다. 상태가 변하게 되면, 리액트 컴포넌트도 변화한 상태에 따라 모습이 바뀌게 된다. 즉 리액트 컴포넌트는 상태가 바뀌면 다시 렌더링 된다.
리액트에서는 화면을 업데이트하는 기능들을 대부분, 상태 즉 State 기능을 통해 구현하게 된다.
import { useState } from 'react'
export default function Body(){
const [light, setLight] = useState("OFF")
return(
<div className='body'></div>
)
}
State를 만드려면 import {useState} from “react”; 를 입력해서 리액트 라이브러리로부터 useState라는 메서드를 불러와야 한다.
useState를 호출하면 함수 컴포넌트 안에서 새로운 State를 생성해 낼 수 있다. 위의 코드에서 useState에 인수로 문자열 “OFF”라는 값을 전달했는데, 이 값은 State의 초기값이다.
const [light, setLight] = useState("OFF")
위는 구조분해 할당으로, 첫 번째 값을 light에, 두번째 값을 setLight에 담는다.
useState는 어떤 배열을 반환하나?
첫번째 요소로는 State의 값을 반환한다. 즉 light에 state의 값이 담긴 것이다. 두번째 요소로는 첫번째 요소로 보낸 State 값을 변경할 수 있는 상태변화함수를 반환한다. 결론적으로 light에는 초기값인 “OFF”이 들어간다.
import './Body.css'
import { useState } from 'react'
export default function Body(){
const [light, setLight] = useState("OFF")
return(
<div className='body'>
{light}
<button onClick={()=>{
setLight("ON");
}}> 켜기 </button>
</div>
)
}
“켜기” 버튼을 눌렀을 때 OFF가 ON으로 변하는 것을 확인할 수 있다. setLight라는 상태변화 함수를 호출하면서 인수로 “ON”을 준다
상태변화함수는 State의 값을, 인수로 전달된 값으로 변경한다. 인수로 전달된 값이 새로운 State값이 되는 것이다. 즉 setLight("ON”);는 light의 값을 ON으로 변경하는 것
State값이 바뀌었다고 어떻게 OFF로 렌더링 되던 것이 ON으로 다시 렌더링 된 걸까?
리액트의 컴포넌트는 자기가 가지고 있는 State 값이 바뀌면 렌더링을 다시 한다. 즉 light 값이 setLight 호출을 통해 바뀌었기에 Body 컴포넌트가 다시 렌더링 된 것이다. 컴포넌트가 렌더링 된다는 것은 결국 함수가 다시 호출되는 것을 의미한다.
JS에는 변수가 있는데, State 말고 변수로 관리하면 안 되나???
버튼을 눌렀을 때 light 값이 ON으로 변경되면서, 화면에 나타나는 값도 ON으로 변경될 것 같지만, “켜키”를 아무리 눌러도 화면은 그대로이다.
리액트의 컴포넌트가 렌더링 되는 조건은 본인이 가진 State가 업데이트되었을 때이다, 즉 위의 코드는 State가 업데이트가 된 것이 아니라 단순히 light 변수 값을 바꿨을 뿐이기에 아무 일도 일어나지 않는다. 즉 컴포넌트 내에서 렌더링에 영향을 미칠 수 있는 동적데이터를 관리할 때는 State를 사용해야 한다.
[State와 props]
자식컴포넌트를 만들어서 State를 자식컴포넌트에게 내려보내본다.
import './Body.css'
import { useState } from 'react'
function Lightbulb({light}){
return(
<>
{light === "ON" ?
<div style={{backgroundColor:"orange"}}> ON </div>
:
<div style={{backgroundColor:"gray"}}> OFF </div>}
</>
)}
export default function Body(){
const [light, setLight] = useState("OFF");
return(
<div className='body'>
<Lightbulb light={light}/>
<button onClick={()=>{
setLight("ON");
}}> 켜기 </button>
<button onClick={()=>{
setLight("OFF");
}}> 끄기</button>
</div>
)
}
Lightbulb 컴포넌트를 만들고, 부모 컴포넌트에서 state값을 props를 통해 Lightbulb 컴포넌트로 내려준다. 이렇게 하면 버튼을 클릭했을 때 Lightbulb 컴포넌트가 다시 렌더링 된다.ON과 OFF를 렌더링 하는 것은 Lightbulb라는 컴포넌트이기 때문이다.
위를 통해 알 수 있는 점은 리액트의 컴포넌트는 자신이 부모 컴포넌트로부터 제공받는 props 값이 변경되면 다시 렌더링 된다.
즉 리액트가 다시 렌더링 되는 조건 두 가지
- 리액트의 컴포넌트는 자기가 가지고 있는 State 값이 바뀌면 렌더링을 다시 한다.
- 부모 컴포넌트로부터 제공받는 props 값이 바뀌면 렌더링을 다시 한다.
StaticLightbulb() 컴포넌트를 만들어서, 항상 OFF 상태를 나타낸다고 해보자
켜기, 끄기 버튼을 눌러도 앞서 만든 Lightbulb 컴포넌트에만 변화가 있을 뿐 StaticLightbulb 버튼은 항상 OFF상태를 유지하고 있다.
그렇기에 겉으로만 봤을 때는 StaticLightbulb 함수는 다시 렌더링 되지 않은 것처럼 보인다. 그리고 항상 OFF 상태이기에 다시 렌더링이 될 이유도 없다
하지만!
console.log를 찍어보면 버튼을 누를 때마다, props값을 전달받지도 않는 StaticLightbulb 컴포넌트가 다시 렌더링 되는 것을 알 수 있다. 리액트는 부모 컴포넌트가 렌더링을 다시 하면, 자식 컴포넌트도 렌더링을 다시 하기 때문이다.
즉 Body 컴포넌트에서 버튼을 클릭할 때마다 State값이 변경되어 다시 렌더링을 실행하므로, 그에 속한 자식 컴포넌트인 StaticLightbulb도 다시 렌더링 하는 것이다.
컴포넌트들이 많이 리렌더링 되면 당연히 웹 성능은 점점 저하된다. 지금은 당장 느낄만한 성능차이는 없지만 추후 더 복잡한 애플리케이션을 만들 때는Staticlightbulb처럼 불필요한 렌더링이 발생할 수 있다. 그렇기에 컴포넌트를 계층구조상으로 배치할 때 부모와 자식 관계를 잘 고려를 해야 한다
부모컴포넌트가 리렌더링이 되었을 때 다시 렌더링 될 필요가 없는 친구까지 리렌더링이 되는 상황을 피하는 게 좋다는 것이다.
최적화의 관점이다.
'프로그래밍 언어 > React 기초' 카테고리의 다른 글
리액트 useEffect (0) | 2023.10.24 |
---|---|
리액트 State로 사용자 입력 관리하기, Ref (0) | 2023.10.10 |
리액트 이벤트 핸들링 (0) | 2023.10.08 |
리액트 props (0) | 2023.10.08 |
리액트 컴포넌트,JSX (2) | 2023.10.05 |