I have a list of 'Activity' objects stored in a Realm DB which are showing on a ListView. There is no problem initially loading the data and showing it on the screen. However, when the data update (in another screen, lets call it 'detail edit screen') and the user returns to the list screen, the list isn't updated.
I tried to setState inside the render method, but that returns a blank screen.
var activities = realm.objects('Activity').sorted('date');
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
...
module.exports = React.createClass({
getInitialState: function(){
return {
dataSource: ds.cloneWithRows(activities),
};
},
...
render: function(){
//update the list of activities
activities = realm.objects('Activity').sorted('date');
this.setState({dataSource: ds.cloneWithRows(activities)});
return (
<View>
{(!activities || activities.length<1) && noActivitiesMessage}
<ListView style={styles.listStyle} dataSource={this.state.dataSource}
renderRow={this._renderRow} />
</View>
)
...
}
I had the same problem like you. My problem was solve by using the Realm ListView. I use it like this
import { ListView } from 'realm/react-native';
class List extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
src = realm.objects('MyObject');
this.setState({
dataSource:this.state.dataSource.cloneWithRows(src),
data:src
});
}
updateData(){
// update or add object in Realm
this.setState({
dataSource:this.state.dataSource.cloneWithRows(this.state.data)
});
}
render(){
return(
<ListView
dataSource={this.state.dataSource}
renderRow=... />
}
}
I would suggest using the react-native-realm
package on NPM (full disclosure, I'm the author, so I'm a little biased). It uses the provider pattern (similar to react-redux) to provide realm data and automatic change event listening (as well as automatic removal of those event listeners) to your components by simply wrapping them in the connectRealm
higher order component and defining which schemas and where to map them in the props of your component.
You could use it like this. In the top level component of your app wrap the sub components with RealmProvider
.
// App.js
// the file you use to wire up your realm schemas, etc.
import realm from './path/to/your/realm/file';
import { RealmProvider } from 'react-native-realm';
import List from './List';
class App extends React.Component {
render() {
<RealmProvider realm={realm}>
<List />
</RealmProvider>
}
export default App;
And then in your sub components if they need realm data use the connectRealm
function to hook into that data.
// List.js
import { ListView } from 'realm/react-native';
import { connectRealm } from 'react-native-realm';
class List extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
}).cloneWithRows(props.activities);
};
}
componentWillReceiveProps(nextProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(nextProps.activities),
});
}
render(){
return (
<ListView
dataSource={this.state.dataSource}
renderRow=...
/>
)
}
}
export default connectRealm(List, {
schemas: ['Activity'],
mapToProps({ activities }) {
return {
activities: activities.sorted('date'), // do extra filtering and sorting here
};
},
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With