mobxjs / mobx-react-lite

Lightweight React bindings for MobX based on React 16.8 and Hooks
https://mobx.js.org/react-integration.html
MIT License
2.13k stars 90 forks source link

useAsObservableSource double renderings #289

Closed Luncher closed 4 years ago

Luncher commented 4 years ago

We are open to your questions or discussion, but keep in mind it might take a while for us to respond. For a faster response, you can try the following channels.

when i read mobx-react docs, i notice one warm tip:

for optimal performance it is recommend to not use useAsObservableSource together on the same component as useObserver (or observer), as it might trigger double renderings. Instead, use Observer component...

I checked the source code of mobx-reaction-lite, but I still don't understand what it is referring to. Can someone please help me out, how did double renderings cause it? thank you very much

urugator commented 4 years ago

useAsObservableSource creates an observable object that is updated every render

const cmp = observer(props => {
  const source = useAsObservableSource({ name: props.name }); // source.name updated every render
  return <span>{source.name}</span> // subscribed for source.name, because it's observer
})

So if such component recieves new props, and props.name differs, it's rendered twice: First time because the props changed. Second time because source.name changed - the update is scheduled during first render, more specifically during the assigment of props.name to source.name. Conceptually it's similar to: https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops

However I don't understand how Observer is going to help here...

Luncher commented 4 years ago

If there are 3 properties on props, all of which have changed, will it be rendered 4 times? @urugator

danielkcz commented 4 years ago

Depends if you change those properties in action or not. React does have batching so the amount of rendering might be less, but it's generally better to be explicit and use an action to batch the change.

urugator commented 4 years ago

@Luncher No. The assigment runs in action, which provides batching, so there will be a single setState call. However even without action, there would be 3 individual setState calls during the same render, so react would schedule a single update anyway.

Luncher commented 4 years ago

@urugator @FredyC thanks a lot