Reputation: 5
My project is built on React, and for state management Mobx is being used. We are not using the decorators, so the components that need to observe the observables, need to be wrapped in the following way:
import React from 'react';
import {observer} from 'mobx-react';
import MyComponent from '../app/my-component.jsx';
import myFilter from './my-filters.jsx';
export default observer(() => {
return <MyComponent filter={myFilter}/>;
});
The component MyComponent
is receiving the observables as props:
static propTypes() {
return {
myFilter: React.PropTypes.function.isRequired
};
}
And it is used in the render method:
render() {
if (this.props.myFilter.filterValue1 !== null) {
// some code here
}
}
myFilter
in this case is the observable, which looks somehow like this:
import {observable} from 'mobx';
const myFilter = observable({
filterValue1: null,
filterValue2: null,
addOrRemoveItem() {
// some function here
}
});
export default myFilter;
In this case, if some component alters myFilter
, the observer MyComponent
which receives the observable as props, does not always re-render. In some cases this can be solved by addressing the observable object by attribute before the call of the component. E.g.:
export default observer(() => {
console.log(myFilter.filterValue1);
return <MyComponent filter={myFilter}/>;
});
But this is not stable. Is there a valid workaround to avoid this?
Upvotes: 0
Views: 1472
Reputation: 25369
Declare MyComponent
as an observer.
export in app/my-component.jsx
should look like this
export default observer(MyComponent);
This piece of code
export default observer(() => {
return <MyComponent filter={myFilter}/>;
});
turns an anonymous stateless component, not MyComponent
, into an observer.
MobX documentation clearly articulates that you need to apply observer
to all components that render observable data or you will encounter problems.
The other way to solve the problem would be passing plain data from this anonymous stateless component into MyComponent
.
export default observer(() => {
return <MyComponent filterValue1={myFilter.filterValue1}/>;
});
This way MyComponent will be rerendered because it receives new props each time its parent is rerendered.
Upvotes: 0
Reputation: 9437
Alik is right, you need MyComponent
to be an observer as well.
Otherwise, your code <MyComponent filter={myFilter}/>
inside the only observable you have means that you want refresh only when myFilter
object (ie., reference to it) changes. It does not access any of its properties and thus refresh is not needed when those properties change. That's why your component was refreshed when you accessed the filterValue1
property in the console.log
statement.
Upvotes: 0