React Native-在数据未更改时强制重新呈现ListView
即使数据源中的数据没有更改,也可以强制ListView重新呈现吗?我在我的应用程序的选项卡栏中有一个ListView,我希望它在每次选择该选项卡时都重新绘制,无论数据是否相同或已更改React Native-在数据未更改时强制重新呈现ListView,listview,reactjs,react-native,Listview,Reactjs,React Native,即使数据源中的数据没有更改,也可以强制ListView重新呈现吗?我在我的应用程序的选项卡栏中有一个ListView,我希望它在每次选择该选项卡时都重新绘制,无论数据是否相同或已更改 this.state = { data: props.data, dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}) } componentWillMount() { this.setState(
this.state = {
data: props.data,
dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
}
componentWillMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(nextProps.data)
})
}
render() {
<ListView
dataSource={this.state.data}
renderRow={this._renderRow}
/>
}
this.state={
数据:道具数据,
数据源:新建ListView.dataSource({rowHasChanged:(r1,r2)=>r1!==r2})
}
组件willmount(){
这是我的国家({
dataSource:this.state.dataSource.cloneWithRows(nextrops.data)
})
}
render(){
}
我尝试使用
rowHasChanged
参数,但没有任何帮助。任何帮助都将不胜感激您可以调用此.forceUpdate()强制重新渲染
您可以在附加到选项卡的简单onClick
处理程序中执行此操作
更多信息
但是,如果有其他规则规定是否应该更新,您可以尝试用新的数据源替换数据源
,使其具有新的引用。这也将使它更新
类似于
this.setState({data:newDataSource…})代码>因此,据我所知,您的用例是由于值的更改而重新呈现ListView的所有行。我不知道value
是什么,由您决定,但我将用value
来解释我的答案:
有几种方法可以解决这个问题。各有利弊:
- 简单方法:只要
!!它告诉React,当值更改时,ListView需要重新呈现(将卸载、重新装载)
- “哈奇方式”。替换为新的数据源。
this.setState({
dataSource:new ListView.dataSource({rowHasChanged:(r1,r2)=>r1==
r2}).cloneWithData(this.props.data)
});
- (imo)最佳实践方式:在数据中,合并
值
,并正确实现行更改。例如:(r1,r2)=>r1.value!==r2.value和r1.data!==r2.数据
({data,value})
)
对我来说,第三个也是最后一个解决方案是最好的,因为:
- 它可以很好地扩展到更多的重新渲染条件(其他
值
s)
- 可能只有部分行需要重新渲染,在这种情况下,不应该为了更好的性能而重新渲染所有行
以下是我在这个问题上给出的另一个答案:
使用不变性方法
“更新”的最佳方法是克隆有问题的数据项,而不是像r1!==r2已经在暗示。通过克隆更改“指针”本身,而不是更新单个项目
对于此特定问题,请按如下方式更新数组中的项
arr[i] = { ...arr[i], someKey: newValue }
这将用“newValue”替换“someKey”属性,并且当前行将有一个新指针
这里有一个很好的资源来了解现代JavaScript中的不变性,这些JavaScript可以反应本机使用:这可能有点过分,但我只是在componentDidUpdate上替换数据源(可能这对性能有害?我不知道哈哈)
我知道我有点晚了,但我相信这仍然是相关的。有一个更简单的方法来解决这个问题。。。Jason提供的第一个例子绝对是一个很好的解决方案,但我想到的是那些容易混淆的人。如果是的话,就用这个
// On component initalization
componentWillMount() {
this.UpdateData();
}
// When the component updates
componentDidUpdate() {
if (this.state.data != this.props.data)
this.UpdateData();
}
// Function to update the ListView component data
UpdateData() {
var source = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.setState({
data: this.props.data,
dataSource: source.cloneWithRows(this.props.data)
});
}
我还建议在应用程序中实现Redux。这样,您就可以将新的、更新的数组值存储在一个reducer中,然后以一种状态本地存储它,然后在componentDidUpdate函数中使用if语句来确定数据是否更新
React调试器不会记录任何基于性能的投诉或警告…可能会在选项卡上添加一个onClick
函数,当该函数被调用时,让它调用渲染函数?谢谢你的回答,我的心都碎了。我不知道r1和r2是指旧的和新的一排。现在变得更有意义了。但愿他们能更好地引用它!有些情况下,“黑客方式”似乎是做你需要的事情的唯一方式。例如,我正在处理一个案例,其中ListView显示的模型列表中的一个模型在应用程序的其他地方被修改。为了显示此更改,我们必须修改整个数据源,因为如果不修改,ListView将什么也不做。这是一个开发人员的意见,认为一个完整的列表应该被视为不变的对象列表中的对象。@ MieaNoKe实现<代码> RoHasStase实际上是选择的机会,如果你认为你的列表对象不变或不可变。这真的取决于你去实现它,只有默认的r1==r2
是一个支持不可变对象的“开发者意见来自React”,但ListView本身不是这个意见(而不是实验性的WindowedListView)rowHasChanged
让您可以控制相等函数和数据的不变性。顺便说一句,这整件事是一种性能折衷,也许我们将来会找到更好的东西。比如@mienaikoe说,黑客的方式在当时很有帮助。还要注意的是,答案是cloneWithData
,这对我不起作用,所以不得不改为cloneWithRow
谢谢@greI一直认为r1
和r2
是与排序((a,b)类似的不同行=>…
。现在我意识到它是prevRow
与nextRow
的对比,rowHasChanged
函数对我来说终于有意义了!
// On component initalization
componentWillMount() {
this.UpdateData();
}
// When the component updates
componentDidUpdate() {
if (this.state.data != this.props.data)
this.UpdateData();
}
// Function to update the ListView component data
UpdateData() {
var source = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.setState({
data: this.props.data,
dataSource: source.cloneWithRows(this.props.data)
});
}