* 본 글은 스스로 공부하면서 정리한 내용입니다. 틀린 부분은 댓글로 남겨주시면 감사하겠습니다! *
Props 와 State에 대해 알아보기
리액트로 만들어진 페이지는 크게 두 가지 로직으로 나눈다고 볼 수 있습니다.
- UI를 구성하는 컴포넌트 로직
- UI 컴포넌트의 상태와 그 상태를 변경하는 로직
Props 와 State는 2번에 해당합니다.
만약 브라우저에 접속한 사용자가 특정 버튼을 클릭할 때 마다, 브라우저에 클릭 횟수를 실시간 반영해서 보여주고 싶다면,
State를 사용해서 클릭 횟수를 업데이트해서 브라우저에 반영해줘야 합니다.
사실 State(상태 관리)는 유일하게 클래스 컴포넌트에서만 할 수 있었습니다. 그래서 개발자들은 함수형 컴포넌트로 로직을 구성하다가 State 관리가 필요하다고 생각되면 클래스 컴포넌트로 리팩토링 해야만 했었습니다.
하지만! 개발자들이 이런 불편함을 그대로 둘리 없습니다. 리액트 16.8 버전에 Hooks가 추가되면서 드디어 함수형 컴포넌트에서도
State를 제어할 수 있게 되었습니다. 갑자기 함수형 컴포넌트의 Hooks에 대해 언급하는 것은 앞으로 useState() 함수를 사용한 상태관리를 예시로 들 것이기 때문입니다.
Hooks의 종류와 설명에 관한 포스팅은 여기 있습니다!
Props
Props는 property의 약자로 단어 그대로 속성을 의미합니다.
컴포넌트에서 컴포넌트로 속성값을 전달해줄 수 있습니다. 흐름은 부모컴포넌트에서 자식컴포넌트입니다.
속성값의 이름은 임의로 정할 수 있습니다.
다음 사용자 컴포넌트 <Welcome />이 있습니다.
const element = <Welcome name="Sara" />;
// element가 <Welcome /> 컴포넌트를 호출합니다.
이 때, 자식컴포넌트에서 전달받은 Props 값을 직접 수정할 수 없습니다..!
즉, props는 읽기전용, 수정불가입니다.
const Welcome = (props) => { // props로 name속성을 받아옵니다. 받아온 props 값은 직접 수정할 수 없습니다!
return <h1>안녕!, {props.name}</h1>;
}
const App = () => {
const element = <Welcome name="Sara" />;
return (
<>
{element}
</>
)
}
Props를 넘겨받은 Welcome 컴포넌트에서는 {props.name}으로 name이란 속성값을 꺼내어 사용했습니다.
만약 넘겨주는 props 값이 위 처럼 name 한 개가 아니라 name, gender 처럼 1개 이상인 경우에도
전체를 props로 넘겨받아 {props.name} , {props.gender}로 꺼내 사용할 수 있습니다.
여기서 props를 매개변수로 넘겨받을 때 값을 바로 꺼내고 싶으면 중괄호를 사용해서 속성값을 바로 써주시면 됩니다.
const Welcome = ({ name, gender ) => {
...
}
이처럼 Props는 수정되지 않는 값을 설정해서 다른 컴포넌트에 넘겨주는 속성 값 입니다.
State
State는 앞서 설명한 것처럼 컴포넌트 내부에서 상태 관리에 이용되는 값입니다.
Props를 먼저 이해했으니 State는 이해가 쉬울 것입니다! State는 Props와 다른점이 명확합니다.
Props는 값이 변하지 않는 정적인 값이라고 한다면, State는 반대로 값이 동적으로 변할 때 이용합니다.
함수형 컴포넌트에서는 State관리를 위해 React Hook인 useState() 함수를 사용합니다.
처음에 예시로 들었던 사용자의 클릭횟수 예시를 다시 가져오겠습니다.
State를 관리하기 위해서는 상태값과 상태값을 변경시킬 함수가 필요합니다.
예시에서 클릭 횟수 : 0의 숫자'0'부분이 기본값으로 설정한 값이고 내부적으로 클릭시 기존 값에 + 1 업데이트하는 함수를 적용했습니다.
그걸 변수로 표현하면,
const [count, setCount] = useState(0)
이런 형식으로 사용할 수 있습니다.
이 글은 React Hooks에 관한 포스팅이 아니기때문에 간략하게 설명해보자면,
State Hook인 useState 함수는 첫 번째로는 상태값, 두 번째로 상태값을 갱신하는 함수를 가지는 배열을 리턴합니다.
관례적으로 State를 갱신시키는 함수는 상태변수값 이름앞에 set을 붙이고 camelCase로 작성합니다.
const [count, setCount] = useState(0);
const [상태값, 상태값 갱신함수] = useState(초깃값);
//초깃값은 첫 호출시에만 사용하고 이후에는 무시됨
상태값 갱신함수로 State값이 변경될 때 마다 리액트는 페이지 전체를 리렌더링하지않고 바뀐 부분만 리렌더링 합니다.
이 부분에서 알 수 있듯이, State는 Props와 다르게 수정이 가능합니다.
그런데 useState() 함수를 이용해서 State값을 갱신시킬 때, 주의해야 할 점이 3가지 있습니다.
- State 값을 직접 변경하지 않아야 한다.
- Object를 가지는 State를 만들 때, State값 갱신을 위해 Object를 복사한 후 그 값을 갱신해야한다.
- 현재 State값을 기반으로 State값을 변경하고자 할 때는 콜백함수로 리턴해서 변경한다.(추천)
클릭 횟수를 갱신하는 Counter 컴포넌트 코드로 주의해야 할 부분을 알아보겠습니다.
다음은 클릭시 카운팅 기능만 있는 기본 counter 컴포넌트입니다.
이 컴포넌트를 약간 개조?시켜 기능을 추가해보겠습니다.
import React, { useState } from 'react'; // State Hook을 사용하기 위해서 import
const Counter = () => {
const [count, setCount] = useState(0); // State 제어
return (
<div>
<p style={{ display: 'inline-block' }}>클릭 횟수 : {count}</p>
<button type="button" onClick={()=>{ // 클릭시 count + 1
setCount(current=>current+1);
}}>클릭</button>
</div>
)
}
export default Counter;
기능추가
import React, { useState } from 'react';
const App = () => {
const [count, setCount] = useState({ count: 0, color: 'black' });
return (
<div>
<p style={{ display: 'inline-block', color: `${count.color}` }}>
클릭 횟수 :
</p>
<button> type="button" onClick={()=>{
setCount(current => {
const newCurrent = { ...current };
newCurrent['count'] += 1;
newCurrent['color'] = 'blue';
return newCurrent;
}
}파란버튼</button>
<button> type="button" onClick={()=>{
setCount(current => {
const newCurrent = { ...current };
newCurrent['count'] += 1;
newCurrent['color'] = 'red';
return newCurrent;
}
}빨간버튼</button>
</div>
)
}
export default App;
클릭시, p 태그의 color가 변하는 파란버튼과 빨간버튼을 추가했습니다.
위 Counter 컴포넌트에서는 State를 setCount라는 함수로 갱신시켜줬습니다.
여기서 만약 갱신함수를 쓰지 않고 다음 코드와같이 State를 직접 변경시켜준다면, State는 불변성을 유지하기 어렵습니다.
불변성을 유지하기 어렵다는말은 갱신시점에 State값이 원하는값이 아닐 수 있다는 뜻이기도 합니다.
이는 상태변경을 리액트가 제대로 추적하지 못해서 리렌더링이 일어나지 않을 수 있습니다.
따라서 setState() 갱신함수를 이용해서 State의 불변성을 보존하고, 보존된 기존 State값과 비교해서 갱신되도록 해야합니다.
const [count, setCount] = useState({ count: 0, color: 'black' });
또한 useState() 함수의 상태 초깃값으로 count, color속성을 가지는 객체가 들어왔습니다.
상태값이 객체나 배열일 경우에는 위에서 말한것과 같이 State를 직접 변경해서는 안 됩니다.
마찬가지로 여기서 State객체를 바로 변경하지않고 복사한 newCurrent 변수를 사용하는 이유는
리액트가 객체안의 State를 변경했다고해서, 객체 그 자체 즉, 틀이 변경되지 않았기 때문에 변화를 감지하지 못합니다.
따라서 리렌더링이 일어나지않게됩니다. 따라서 기존의 State객체와 똑같은 객체를 만들어 리턴함으로써 State를 갱신해서 변화를 던져줍니다.
이처럼 State는 컴포넌트 내에서 유동적인 값을 사용하고 싶을 때 이용하는 값입니다!
Props 와 State의 차이점
Props는 읽기전용 값이고, State는 수정가능한 유동적인 값입니다.
Props는 속성값으로 컴포넌트끼리 전달하는 방식이고, State는 컴포넌트 내에서 관리되는 값입니다.
정리
리액트는 UI 컴포넌트로 페이지를 구성하는데 그 컴포넌트에서 사용되는 값을 관리하기 위해 Props와 State를 사용합니다.
상태값은 정적/동적 유무에따라 Props로, useState() 갱신함수를 사용하는 State로 나눠집니다.
상태값은 직접 변경해서는 안되며, 갱신함수를 사용해서 변경해야 리액트가 정상적으로 변화를 감지하고 상태값을 갱신합니다.!
참고 - https://ko.reactjs.org/docs/faq-state.html#what-is-the-difference-between-state-and-props
https://mari-mo.tistory.com/214
* 본 글은 스스로 공부하면서 정리한 내용입니다. 틀린 부분은 댓글로 남겨주시면 감사하겠습니다! *
'FRONTEND > React' 카테고리의 다른 글
[테스팅 초기 설정] Jest + yarn-berry + Nextjs + Recoil + TypeScript (0) | 2023.06.30 |
---|---|
[React] 리액트 useState 개념 (0) | 2022.12.02 |
[React] 리액트 프로젝트 시작 세팅하기(CRA) (0) | 2022.11.20 |
[React] React.js 리액트 특징! 간단하게 알아보자 (0) | 2022.11.16 |