이전글에서 MobX의 makeObservable
과 makeAutoObservable
함수에 대해 기록해두었다. 이 글에서는 observer
함수가 반환하는 컴포넌트 및 MobX 상태 변경 시 재렌더링하는 방식에 대해 간단히 기록해보려 한다.
(혹시나 이 글을 보시는 분들께: 틀린 내용이 많을 수 있습니다..! 참고용으로만 봐주시면 감사드리겠습니다.)
observer 함수는 데코레이터로 사용할 수도 있고, 리액트 컴포넌트를 감싸 사용할 수도 있다. 또한, makeObservable 또는 makeAutoObservable 함수로 생성한 MobX 스토어를 컴포넌트의 props로 넘겨와 사용할 수도 있고, React context로 공유된 스토어를 사용할 수도 있다.
import { observer } from 'mobx-react';
import { useContext } from 'react';
// props로 스토어를 넘기는 예시
const ComponentExample = observer(({ MobxStoreExample }) => {
// MobX observable로 생성한 MobxStoreExample을 사용할 수 있음
return <div></div>;
});
// React context로 스토어를 사용하는 예시
const ComponentExample = observer(() => {
// store에서 createContext로 생성한 컨텍스트를 export한다는 가정
// useMobxStoreExample로 MobX store 접근
const useMobxStoreExample = useContext(MobxStoreExample);
return <div></div>;
});
mobx-react 라이브러리의 observer 함수는 아래처럼 리액트의 컴포넌트를 매개변수로 받는다.
기존 MobX v4, v5에서는 클래스형 컴포넌트만 반환했지만, MobX v6에서는 함수형 컴포넌트인지 클래스형 컴포넌트인지에 따라 반환하는 방식이 조금 다르다.
간단하게만 보면 함수형 컴포넌트일 경우 observerLite 함수를 반환하는데, 이 observerLite 함수는 mobx-react-lite
라이브러리의 observer 함수이다. 함수형 컴포넌트가 아닐 경우(클래스형 컴포넌트일 경우)에는 makeClassComponentObserver
라는 함수를 반환한다.
mobx-react-lite 라이브러리의 observer 함수는 기본적으로 함수형 컴포넌트만
을 매개변수로 받는다는 점이 mobx-react의 observer 함수와 다르다 (mobx-react-lite 라이브러리를 사용하면 함수형 컴포넌트만을 사용할 수 있는 것으로 추정된다).
observer 함수 내부에서는 observable의 변경을 감지하기 위해 매개변수로 받은 컴포넌트를 useObserver
함수로 감싼다.
이 wrappedComponent
를 React.memo
로 감싼 컴포넌트를 반환하여 불필요한 리렌더링을 방지한다.
일반적으로 리액트는 props의 변경을 감지하여 컴포넌트를 리렌더링하는데, 이 때 props의 깊은 비교를 수행한다. MobX가 memoComponent
를 생성하는 이유가 여기에 있는 것 같다. 이미 리액트에서 props의 깊은비교
를 수행해주고 있기 때문에, MobX에서는 memo로 감싸 얕은비교
만을 수행하여 리렌더링의 효율성을 높이는 것으로 이해하고 있다.
mobx-react-lite 라이브러리의 useObserver
함수는 리액트의 useState
를 사용한다. 이를 이용하여 forceUpdate
라는 함수를 생성하여 컴포넌트 첫 마운트 시, 그리고 마운트 전 observable 변경 발생 시 이 함수를 실행하여 리렌더링을 수행한다.
forceUpdate 함수 생성
첫 마운트 시 forceUpdate 함수 호출마운트 전 observable 변경 시 forceUpdate 함수 호출
mobx-react 라이브러리의 observer 함수는 클래스형 컴포넌트일 경우 makeClassComponentObserver
함수를 반환한다. 매개변수로 받은 컴포넌트를 makeComponentReactive
라는 함수에 바인딩한다.
해당 함수는 Reaction 객체의 인스턴스를 생성하며, 해당 인스턴스는 컴포넌트 마운트 시 리액트 라이브러리 내부에 있는 forceUpdate 메소드를 수행한다.
위 리액션 객체의 인스턴스는 observable의 변경이 감지될 때마다 자동으로 객체 내부 runReaction
이라는 메소드를 실행하는데, 이 메소드 내부에 forceUpdate
메소드가 실행되도록 되어있어 리렌더링을 수행하게 된다.
[MobX 공식 문서] React integration
mobx-react, mobx-react-lite 라이브러리 소스 코드