props | vs | state |
---|---|---|
부모 컴포넌트가 자식 컴포넌트에게 전달하는 값 | 자신이 스스로 관리하는 상태값 | |
값을 자신이 변경할 수 없음 | 값을 자신이 변경할 수 있음 |
componenet에서 상위 componenet에서 받아오는 데이터 뿐만 아니라, 자신이 변경하고 사용해야하는 데이터가 있기 때문에, 그러한 데이터들을 관리하기 위해서 필요하다. 객체지향형 프로그래밍에 있어서 필수 적이다.
평소 생각하는 불변성과는 다르게 "직접 변경하지 않는다"라는 의미이다. 리액트는 virtualDOM을 통해 이전과 지금의 변경된 부분이 무엇이 있는 지 확인을 한 뒤 변경된 부분만 업데이트 해주는 효율적인 lifecycle을 가지고 있다. 그런데 state를 직접 변경하게되면, state가 변경되었다는 것을 리액트가 인지 하지 못해 rerendering을 하지 않아, 사용자가 보이는 화면에 업데이트 되지 않고, React의 lifecycle에 맞게 작동하지 않는다.
const [state,setState]=useState({name:"abc",age:19})
//변경 불가
state[firstName]="jack"
setState(state);
//변경가능
const newState ={...state, firstName:"jack"};
setState(newState);
원시타입 | vs | 참조타입 |
---|---|---|
boolean, number,string | Object | |
불변성을 가지고 있다. | 불변성을 가지고 있지 않다. | |
변수에 원시 타입의 값을 할당하면, 메모리에 값 자체가 저장된다. | 변수에 참조타입의 값을 할당하면, 메모리 값이 담긴 주소가 저장된다. |
이 말은 React에서 setState가 여러번 호출이 된다면(같은 state에 대해서), 굳이 여러번 state를 동작시키는 것이 아니라 비동기적으로 마지막에 한번 업데이트 시킬 수 있다.
중간에 업데이트 되는 과정들도 모두 화면에 보여져야 하는 상황이라면, 상당히 당황스러운 상황이다. 나도 중간 과정을 보여주기 위해 강제로 렌더링 시키기위해 노력했던 경험이 있다.
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
아래의 독립적인 clock에서 나만의 타이머를 설정 및 업데이트 할 수 있다.
function App(){
return(
<>
<clock/>
<clock/>
<clock/>
</>
);
}
컴포넌트가 많아지고 자식 컴포넌트가 늘어나게되면 G에서 사용하는 데이터를 C에서 받아오게 된다면, D,E,F는 필요없는 State를 받아오고 넘겨 주어야 된다.
해결방법: 전역 저장소를 만들면, 전역 저장소에서 직접 받아오고, 직접 state를 제공하면 된다.
예를들어 로그인은 가장 윗단에서 실시를 하게 되는데, 그 로그인 유저 정보를 사용하는 컴포넌트를 위해 사용하지 않는 중간 단계들을 모두 거쳐서 말단 컴포넌트까지 내려가게 되는 이슈가 발생하고, 제어가 복잡해 진다.
GrandParent-Parent-Children의 구조에서 GrandParent에서 선언한 state를 Parent를 거치지 않고, Children으로 보낼 수 있는 library이다.
Redux는 가장 널리 사용되는 state management tool로 기업 채용 공고를 보면 Redux 사용 가능자를 우대한다는 공고도 많이 있을 정도이다. 아래 recoil과 다르게 자바스크립트 앱을 위한 상태 컨테이너로 만들어 졌다. Redux 개념은 store와 reducer로 이루어져 있다.