我有一个存储在Realm DB中的'Activity'对象列表,它们显示在ListView上。 最初加载数据并在屏幕上显示数据没有问题。但是,当数据更新时(在另一个屏幕中,我们称之为'详细编辑屏幕')并且用户返回列表屏幕,列表不会更新。
我尝试在render方法中设置setState,但是返回一个空白屏幕。
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>
)
...
}
答案 0 :(得分:4)
我遇到了和你一样的问题。我的问题是使用Realm ListView解决的。我像这样使用它
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=... />
}
}
答案 1 :(得分:3)
我建议在NPM上使用react-native-realm
包(完全披露,我是作者,所以我有点偏颇)。它使用提供者模式(类似于react-redux),通过简单地将它们包装在connectRealm
高阶组件中,为组件提供领域数据和自动更改事件监听(以及自动删除这些事件监听器)。定义哪些模式以及在组件的道具中将它们映射到何处。
你可以像这样使用它。在应用的顶级组件中,使用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;
然后在您的子组件中,如果他们需要领域数据,请使用connectRealm
函数挂钩该数据。
// 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
};
},
})
答案 2 :(得分:1)
正如您在评论中已经提到的,可能无法在渲染函数中调用setState
(它基本上会导致无限递归)。
这里最简单的解决方案是在构造函数中添加一个侦听器,对于您的示例,它将如下所示:
realm.addListener('change', () => {
this.setState({dataSource: realm.objects('Activity').sorted('date'); })
});
答案 3 :(得分:0)
这是我的方法,感谢@ Johannes的回答以及@ tiby使用领域列表视图的建议。
constructor (props) {
super(props)
this.state = {
ds: new ListView.DataSource({
rowHasChanged (a, b) {
return a.done !== b.done || a.text !== b.text || a.items || b.items
}
}),
src: realm.objects(‘Object’),
}
realm.addListener('change', () => {
this.setState({src: realm.objects(‘Object’) })
});
}
render () {
var dataSource = this.state.ds.cloneWithRows(this.state.src)
return (
<ListView
dataSource={dataSource}
…
/>
)
}