Computed라고 하는 것은 지금까지 배웠던 observable state에서 뭔가 변경이 일어났을 때 실제로 observable state를 바로 렌더해서 사용하는게 아니고 computed라고 하는 실제 렌더를 변경하는 일으키는 항목을 define을 시키고 우리가 사용하는 컴포넌트에서는 computed 상태만 변경되었을 때 렌더를 다시 하는 방향으로 observable의 모든 state 변경에 반응하지 않고 computed 상태를 중간단계에서 처리하는 일종의 캐싱형태의 단계이다.
두 가지 방식
- computed(내부에서 observable을 사용하는 함수)
- 데코레이터 없이 사용하는 방식이다
- <0bservable 클래스>의 getter에 @computed 달아서 처리
- 스토어에 사용
- getter에만 붙일 수 있다!
- getter는 함수가 아니라 리액티브 하다는 것에 주목 ⇒ 어떤 신호가 오게되면 신호에 따라서 연산이 다시 진행되는 형식이다.
- 실제 컴포넌트에서 사용하는 (getter)값들에 달아서 사용하면 최소 범위로 변경할 수 있기 때문에 유용하다.
- 예를들어, 40살이 넘었을 때만 나이를 올리면 40살 이하는 재렌더링 대상이 아닌 것과 같은 경우
- 내부적으로 고도의 최적화를 한다 어떻게? ⇒
- 매번 재계산을 하지 않는다
- 계산에 필요한 observable 값이 변경되지 않으면 재실행하지 않는다
- 다른 computed 또는 reaction에 의해 호출되지 않으면 재실행되지 않는다
- observable이 변했는데 computed가 변하지 않을 때 렌더하지 않는다
지난 코드를 이어서 보면 우리는 App.js에 personStore에 age라고 하는 observer 항목을 바로 렌더링하고 있었다. 그렇기 때문에 observer들이 변하게 되면 렌더링이 매번 다시 되었었다. 이번에는 매번 렌더링이 되지 않기 위해서 실제 나이가 아니라 30대 40대 방식으로 표현해보자.
@observer
class App extends React.Component {
static contextType = PersonContext;
@autobind
click() {
const personStore = this.context;
personStore.plus();
}
render() {
const personStore = this.context;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
<button onClick={this.click}>plus</button>
</p>
<p>{personStore.age10}</p>
</header>
</div>
);
}
}
export default observer(App);
- age10이라는 항목을 불러보자
// PersonStore
export default class PersonStore {
@observable
name = "Mark";
@observable
age = 39;
get age10() {
return Math.floor(this.age / 10) * 10;
}
constructor() {
makeObservable(this);
}
plus() {
this.age++;
}
}
- get age10이라는 나이대를 구하는 함수를 작성하자
- Math.floor()로 29살이면 20대 39살이면 30대가 나오도록 만들었다
- 하지만 age는 observable로 된 것이기 때문에 age10함수느 observable이라고 생각해야 한다. 그렇기 때문에 observable로 처리된 것을 가지고 있는 getter도 매번 렌더링이 되는 형식을 제공한다
- 우리가 age10이 변했을 때만 렌더를 하고 싶을 때 computed 설정을 하면 된다
@computed
get age10() {
return Math.floor(this.age / 10) * 10;
}
- 이렇게 하면 computed에 실제 결과물이 바뀌었을 때만 렌더가 다시 일어나기 때문에 모든 observable을 observe에서 처리하는게 아니라 computed 이용해서 렌더하는게 올바른 사용 방법이다
이번엔 함수 컴포넌트에서 함수로 만들어 사용해보자
function App() {
const personStore = useContext(PersonContext);
const age10 = computed(() => {
return Math.floor(personStore.age / 10) * 10;
}).get();
const click = () => {
personStore.plus();
};
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
<button onClick={click}>plus</button>
</p>
<p>{age10}</p>
</header>
</div>
);
}
- age10 변수에 computed를 가져와서 실행하고 안에 함수를 넣는다
- 리턴은 똑같이 하지만 결과물을 age10에 담아야 되기 때문에 .get()으로 실행해 주면 computed 결과로 나온 값이 저장된다
- computed를 달아서 안에 함수를 넣고 그 함수가 변경이 됐을 때 age10을 받아다가 새로 렌더하는 형식으로useMemo()같은 느낌이 든다
'Front-End > MobX' 카테고리의 다른 글
@inject 와 Provider (0) | 2022.12.16 |
---|---|
@action (0) | 2022.12.15 |
@Observer (0) | 2022.12.15 |
@Observable (0) | 2022.12.15 |
프로젝트에 Decorator 설정하기 (0) | 2022.12.15 |