observer
컴포넌트 내에서 역참조가 이루어져야 tracking이 발생한다. 바깥에서 역참조 하고 props 넘겨주면 tracking 은 발생하지 않는다. observer
는 ‘역참조' 라는 행위에 반응하기 때문이다.observer
컴포넌트가 아닌 애 한테는 observable 넘겨주면 안된다. observable 객체 참조값을 넘겨주면 변화를 감지 못해버리니 렌더링 못한다. 이럴때는 그냥 새로운 객체를 만들어서 넘겨야 한다.observer
컴포넌트가 아니면서 Callback Component(콜백을 호출하는 컴포넌트)라면, <Observer />
로 인라인으로 컴포넌트를 만들어주면 좋다. (https://mobx.js.org/react-integration.html#callback-components-might-require-observer)이 코드가 동작하는 이유
const TodoView = observer(({ todo }: { todo: Todo }) => {
// WRONG: GridRow.onRender won't pick up changes in todo.title / todo.done
// since it isn't an observer.
return <GridRow onRender={() => <td>{todo.title}</td>} />
// CORRECT: wrap the callback rendering in Observer to be able to detect changes.
return <GridRow onRender={() => <Observer>{() => <td>{todo.title}</td>}</Observer>} />
})
대충 그림을 그려보자면, <GridRow />
컴포넌트가 리턴되고 환경레코드가 보존되면서 todo 라는 observable이 같이 보존되게 되는데, 이와 onRender 콜백의 관계가 마치 외부의 observable 을 참조하는 render 함수의 형태로 나타나게 된다. 이러한 이유로 onRender는 <GridRow />
컴포넌트의 렌더링 플로우를 타는 것이 맞다. 그러므로 얘도 observable 변화를 감지하기 위해 observer
가 돼야 하는데, GridRow 는 3rd party component 이므로, onRener 함수 콜백 정의 내에서 <Observer />
컴포넌트를 인라인으로 감싸주는 것이다