참조?에 대한 고찰
객체 참조 등에 대한 고찰
계기
불필요 하다고 생각되는 컴포넌트 리랜더링을 발견.
상황
리덕스 전역 상태 관리 > 채팅 방을 구분하기 위한 값 참조하는 메뉴 >
다른 페이지에서의 객체 내 다른 값 변경 dispatch >
위에서 변경한 값이 아닌 객체의 다른 값을 참조하고 있는 메뉴 리랜더링
ex)
const initialState = {
//* currentRoom 참조
currentRoom: "",
...
//* 아래의 msgs 값을 업데이트 하는 action 발생
//* 위의 currentRoom참조 페이지 리 랜더링 발생
msgs: []
};
리덕스는 상태를 받아와서 사용 할 때 기본적으로 최적화가 잘 되어 있어
필요한 상태가 변경될 때에 리랜더링 될 수 있다고 알고 있었는데...암튼...
일단 구글링한 결과와 찾아보며 조금 공부한 결과 원인은 상태 객체 참조
부분에 있는 것 같았다.
원인
//! 타입은 생략
//! rootReducer
//! 예시 객체
//! combineReducers({
//user: userReducer,
//post: postReducer
)};
// 예를 들어 스토어가 이렇다고 치자
{
user: {
name: "" ,
age: 0,
role: "user" ,
...
},
post: {
....
}
}
// 상태 참조 하는 컴포넌트
// age의 변경에 따른 리랜더링이 필요한 컴포넌트라 치자
const Age = () => {
const { age } = seSelector((store) => store.user);
return <span>{age}</span>
};
// 다른 컴포넌트에서 name만 업데이트 하는 action dispatch
// Age 컴포넌트 리랜더링!!!!!
평소에 위와 같은 방식으로 상태를 참조 하였었다.
눈치가 빠른 분이라면 벌써 눈치 채셨을 수도 있을 것이다.
그렇다....구조 분해 할당 요놈이 문제였던 것이다...
구조 분해 할당은 구조화된 배열과 같은 이터러블 또는 객체를 비구조화, 파괴하여 1개 이상의 변수에 개별적으로 할! 당! 하는 것을 말한다. [참고]: 모던자바스크립트 DeepDive
즉 변수를 새로 만들어 값을 할당 하는 것이다.
useSelector에서 반환한 값을 새로운 변수에 할당하기에 주소값이 달라진다.
구조 분해 할당으로 인해 새로운 주소에 store의 필요한 값이 할당이 된 것이다.
주소 값이 바뀌었기 때문에 컴포넌트에서 참조하던 값이 변경되지 않았음에도
컴포넌트가 참조하는 상태의 주소값이 다른 곳을 바라 보고 있기 때문에
값이 바뀌었다고 판단되어 다시 랜더링이 일어나는 것이다.
사실 처음 검색 했을때는 딱 아 이거구나 라는 느낌이 있었는데...
글을 점점 쓰면서 정확하게 풀기 위해 검색하고 공부하며 생각하는데
뭔가 조금 혼란스러운 부분이 글을 쓰며 생겼다.
일단은 내가 이해한 부분으로 작성할 것이고, 틀릴 수도 있으니 양해 부탁 드립니다.
오류가 있다면 채팅으로 문의 바랍니다.
# 객체 참조 등에 대한 고찰 ### 계기 불필요 하다고 생각되는 컴포넌트 리랜더링을 발견. ### 상황 리덕스 전역 상태 관리 > 채팅 방을 구분하기 위한 값 참조하는 메뉴 > 다른 페이지에서의 객체 내 다른 값 변경 dispatch > 위에서 변경한 값이 아닌 객체의 다른 값을 참조하고 있는 메뉴 리랜더링 ## ex) ```js const initialState = { //* currentRoom 참조 currentRoom: "", ... //* 아래의 msgs 값을 업데이트 하는 action 발생 //* 위의 currentRoom참조 페이지 리 랜더링 발생 msgs: [] }; ``` 리덕스는 상태를 받아와서 사용 할 때 기본적으로 최적화가 잘 되어 있어 필요한 상태가 변경될 때에 리랜더링 될 수 있다고 알고 있었는데...암튼... 일단 구글링한 결과와 찾아보며 조금 공부한 결과 원인은 상태 객체 참조 부분에 있는 것 같았다. ### 원인 ```js //! 타입은 생략 //! rootReducer //! 예시 객체 //! combineReducers({ //user: userReducer, //post: postReducer )}; // 예를 들어 스토어가 이렇다고 치자 { user: { name: "" , age: 0, role: "user" , ... }, post: { .... } } // 상태 참조 하는 컴포넌트 // age의 변경에 따른 리랜더링이 필요한 컴포넌트라 치자 const Age = () => { const { age } = seSelector((store) => store.user); return <span>{age}</span> }; // 다른 컴포넌트에서 name만 업데이트 하는 action dispatch // Age 컴포넌트 리랜더링!!!!! ``` 평소에 위와 같은 방식으로 상태를 참조 하였었다. 눈치가 빠른 분이라면 벌써 눈치 채셨을 수도 있을 것이다. 그렇다....구조 분해 할당 요놈이 문제였던 것이다... > 구조 분해 할당은 구조화된 배열과 같은 이터러블 또는 객체를 비구조화, 파괴하여 1개 이상의 변수에 개별적으로 할! 당! 하는 것을 말한다. > [참고]: 모던자바스크립트 DeepDive 즉 변수를 새로 만들어 값을 할당 하는 것이다. useSelector에서 반환한 값을 새로운 변수에 할당하기에 주소값이 달라진다. 구조 분해 할당으로 인해 새로운 주소에 store의 필요한 값이 할당이 된 것이다. 주소 값이 바뀌었기 때문에 컴포넌트에서 참조하던 값이 변경되지 않았음에도 컴포넌트가 참조하는 상태의 주소값이 다른 곳을 바라 보고 있기 때문에 값이 바뀌었다고 판단되어 다시 랜더링이 일어나는 것이다. 사실 처음 검색 했을때는 딱 아 이거구나 라는 느낌이 있었는데... 글을 점점 쓰면서 정확하게 풀기 위해 검색하고 공부하며 생각하는데 뭔가 조금 혼란스러운 부분이 글을 쓰며 생겼다. 일단은 내가 이해한 부분으로 작성할 것이고, 틀릴 수도 있으니 양해 부탁 드립니다. 오류가 있다면 채팅으로 문의 바랍니다.