Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

componentWillReceiveProps not working? #281

Closed
xzilja opened this issue Jun 18, 2017 · 12 comments
Closed

componentWillReceiveProps not working? #281

xzilja opened this issue Jun 18, 2017 · 12 comments

Comments

@xzilja
Copy link

xzilja commented Jun 18, 2017

for some reason I can't get componentWillReceiveProps to trigger when mobx props are updated, yet componentWillUpdate gets triggered just fine. Any suggestions on what could be causing this?

@xzilja
Copy link
Author

xzilja commented Jun 18, 2017

EDIT: I am accessing these via Provider and inject("store") where store holds various store classes i.e this.props.store.notification.message

@urugator
Copy link
Contributor

urugator commented Jun 19, 2017

componentWillReceiveProps is called only when props object itself is changed.
This happens only when the parent component is being re-rendered and passes updated props to your component.
It won't be called if nested objects like this.props.store.notification are modified.
Mobx doesn't update components by passing new props, it calls forceUpdate if any observable (not just props) accessed in render was modified.
In your case componentWillReceiveProps would be called if you would change store in parent component, but because the store is passed via ctx and things on ctx must be final, it will never happen.
EDIT: I should also probably mention that observer implements "PureRenderMixin" therefore the updated props are compared shallowly...

@xzilja
Copy link
Author

xzilja commented Jun 19, 2017

By the looks of it componentWillReceiveProps can take in second argument for changed context as referenced here https://facebook.github.io/react/docs/context.html#referencing-context-in-lifecycle-methods

@xzilja xzilja closed this as completed Jun 19, 2017
@urugator
Copy link
Contributor

Followed by

Updating Context
Don't do it.
React has an API to update context, but it is fundamentally broken and you should not use it.

:)

And from Mobx docs:

Values provided through Provider should be final, to avoid issues like mentioned in React #2517 and React #3973, where optimizations might stop the propagation of new context. Instead, make sure that if you put things in context that might change over time, that they are @observable or provide some other means to listen to changes, like callbacks. However, if your stores will change over time, like an observable value of another store, MobX will warn you. To suppress that warning explicitly, you can use suppressChangedStoreWarning={true} as a prop at your own risk.

@xzilja
Copy link
Author

xzilja commented Jun 19, 2017

@urugator what if it's not context updating? i.e. I call function that sets new value in mobx class, exactly how docs show and I expect to receive new value with it flowing down through <Provider />

Reason for me using provider is to have global store that is easily accessible through @inject in any component, is this an anti pattern of sorts?

@urugator
Copy link
Contributor

Reason for me using provider is to have global store that is easily accessible through @Inject in any component, is this an anti pattern of sorts?

No it's what it's made for. I was just trying to explain when and why componentWillReceiveProps is (not) called.

@aseem2625
Copy link

aseem2625 commented Nov 13, 2017

@urugator
I faced this problem recently. componentWillUpdate will be called but since mobx works by forceUpdate, you can never compare existing and next value(if modified). Eg: I'm having isLoading observable in mobx store initialised with true. On ajax resolve, I'm update isLoading to false. But in componentWillUpdate, this.props.isLoading and nextprops.isLoading are both false.

Syntax:

this.isLoading = observable.box();
this.isLoading.set(true);

this.isLoading.set(false); // where ajax is successful

Any idea how to handle this(I want to compare existing and nextProps and do something if their value is not same)?

@urugator
Copy link
Contributor

urugator commented Nov 13, 2017

@aseem2625

There is no such concept as prev and next state in MobX, there is just current state.
Therefore you can't never compare prev and next value inside the isLoading observable.

You can always compare prev and next props in React component.
Therefore you can always compare prev and next prop value like props.isLoading === nextProps.isLoading

What you can do is to transform your observable value change to prop value change:

inject(() => ({
  isLoading: store.myStore.isLoading.get()  
}))(props => React.createElement("div", null, props.isLoading))

// the same can be done without inject, you will need 2 components - parent using observable and child using plain prop  

However the need to compare prev and next state seems a bit fishy in the first place...

@charlie0077
Copy link

So, what is the best practice of implementing logic that requires observing props change?

@silent-tan
Copy link

silent-tan commented Dec 7, 2017

the same problem, it it possible to support the componentWillReceiveProps running while the observable value changed?

@Hypothesis-github
Copy link

This problem is still unsolved, any work around ?

@mweststrate
Copy link
Member

This issue is closed, but normal mobx mechanisms apply; use reaction or observe to detect prop changes, or just split up your component in a plain and mobx part (for example by using Observer sections instead of @observer decorators.

This issue is closed, for follow up questions please open fresh issues with concrete use cases

@mobxjs mobxjs locked as resolved and limited conversation to collaborators Jul 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants