React Native ListView 不会通过单击重新呈现状态更改
Posted
技术标签:
【中文标题】React Native ListView 不会通过单击重新呈现状态更改【英文标题】:React Native ListView not re-rendering on state change by click 【发布时间】:2016-11-09 18:01:24 【问题描述】:这是我的示例代码,我希望在点击时更新 ListView
元素。
这一行定义了样式:
(this.state.selectedField.id==field.id)?'green':'white'
在此示例中,活动的View
应以绿色突出显示。 handleClick()
内部的状态正在更新,但没有调用 renderField()
方法。
如何让ListView在点击触发状态改变时重新渲染?
RNPlayNative Link
import React, Component from 'react';
import
AppRegistry,
View,
ListView,
Text,
TouchableOpacity
from 'react-native';
class SampleApp extends Component
constructor(props)
super(props);
var ds = new ListView.DataSource(
rowHasChanged: (row1, row2) => row1 !== row2,
);
this.state =
fields: ds.cloneWithRows([
id:0,id:1,id:2
]),
selectedField: id:0
;
handleClick(field)
console.log("Selected field:",field);
this.setState(
selectedField: field
);
renderField(field)
return (
<TouchableOpacity onPress=this.handleClick.bind(this, field) >
<View style=backgroundColor:(this.state.selectedField.id==field.id)?'green':'white'>
<Text style=left:0, right:0, paddingVertical:50,borderWidth:1>field.id</Text>
</View>
</TouchableOpacity>
);
render()
return (
<View>
<ListView
dataSource=this.state.fields
renderRow=this.renderField.bind(this)
/>
</View>
);
AppRegistry.registerComponent('SampleApp', () => SampleApp);
【问题讨论】:
试试这个:***.com/questions/26882177/… 我已经在使用内联样式了,问题在于动态链接样式到点击等事件的状态。 【参考方案1】:已经回答过很多次了,如果你想改变一个props上的行渲染,如果你想行更新,这个props需要进入你的数据。
查看以下 2 个答案:
https://***.com/a/38001185/343892
https://***.com/a/34718220/343892
【讨论】:
【参考方案2】:这是我对问题的解决方案,但处理每次点击仍然需要很长时间:
handleClick(field)
newFields = this.state.fields.map( (x) => x.key === field.key && x.active !== true ? ...x,active:true : ...x,active:false)
this.setState(
fields:newFields,
dataSource: this.state.dataSource.cloneWithRows(newFields)
);
【讨论】:
【参考方案3】:当数据源更改时,列表会再次呈现,在您的示例中,由于数据源永远不会改变,因此列表视图永远不会重新呈现。这可以通过在状态变量中添加一个字段来保存 dataSource 的数据来实现。在 componentDidMount 方法中,让 dataSource 克隆具有数据状态变量的行。每当您想重新渲染列表视图时,您只需更改数据状态变量,列表将自动重新渲染。我已经更改了您的数据,以便为每个对象添加一个选定状态。这是更新后的代码。
class SampleApp extends Component
constructor(props)
super(props);
var ds = new ListView.DataSource(
rowHasChanged: (row1, row2) => row1 !== row2,
);
var dataVar = [
id:0,
selected: true,
,
id:1,
selected: false,
,
id:2,
selected: false,
];
this.state =
data: dataVar,
fields: ds,
;
componentDidMount()
this.setState(
fields: this.state.fields.cloneWithRows(dataVar)
);
handleClick(field)
console.log(field);
field.selected = !field.selected;
var dataClone = this.state.data;
console.log(dataClone);
dataClone[field.id] = field;
this.setState(
data: dataClone,
);
renderField(field)
let color = (field.selected == true)?'green':'white';
return (
<TouchableOpacity onPress=this.handleClick.bind(this, field) >
<View style=backgroundColor:color>
<Text style=left:0, right:0, paddingVertical:50,borderWidth:1> field.id</Text>
</View>
</TouchableOpacity>
);
render()
return (
<View>
<ListView
dataSource=this.state.fields
renderRow=(field) => this.renderField(field)
/>
</View>
);
这是一个有效的 rnplay sample
【讨论】:
你忘了在componentDidMount
中修复这条线:fields: this.state.fields.cloneWithRows(this.state.data)
我尝试了解决方案,但由于某种原因,我无法在更新data
时触发renderField()
功能。 handleClick()
工作正常,data
得到更新。
好的,到目前为止,我已经成功了。我的应用程序有这行:if (!this.state.loaded) return this.renderLoadingView();
用于推迟视图渲染,直到加载数据,由于某种原因阻止了 renderField()
调用。以上是关于React Native ListView 不会通过单击重新呈现状态更改的主要内容,如果未能解决你的问题,请参考以下文章
react-native ListView - 我只需要渲染 DataSource 中的一些对象