如何更新 FlatList 项目的属性?
How to update the attribute of an item of a FlatList?
我编写了一个 Android 应用程序,它由一个 TextInput、一个 Button 和一个 FlatList 组成。对于在 TextInput 中写入的每个名称,平面列表中都会有一个项目。项目标题将是 TextInput 内容,列表项目旁边将有两个按钮和一个文本。一个按钮用于将 Text 显示的数字增加 1,另一个按钮用于减少。这是我的代码:
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
FlatList,
TouchableOpacity,
} from 'react-native';
import { ListItem, SearchBar} from 'react-native-elements';
class App extends Component {
constructor(props) {
super(props);
this.state = {
task: "",
task_array: [],
};
}
ChangeText = (some_task) => {
this.setState({task: some_task});
};
pushAdd = () => {
let contact = {
name: this.state.task,
counter: 0,
};
this.setState({task_array: [...this.state.task_array, contact]});
};
renderListItem = ({item}) => {
return(
<View style={{flexDirection: 'row'}}>
<ListItem title={item.name} style={{width:'75%', marginLeft:20}}></ListItem>
<View style={{flexDirection:'row'}}>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50}} onPress={()=> item={name:item.name, counter:item.counter + 1}}><Text>+</Text></TouchableOpacity>
<Text>{item.counter}</Text>
//main problem <TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50 }} onPress={() => item = { name: item.name, counter: item.counter - 1 }}><Text>-</Text></TouchableOpacity>
</View>
</View>
);
};
render() {
return(
<View style={{ backgroundColor: 'mediumturquoise', width:'100%', height:'100%'}}>
<FlatList
data = {this.state.task_array}
renderItem = {this.renderListItem}
keyExtractor = {(item) => item.name}>
</FlatList>
<View style = {{flexDirection : 'row', alignContent:'center', alignItems:'center'}}>
<TextInput onChangeText={this.ChangeText} style={{ backgroundColor: 'burlywood', height:50, width:'75%', borderRadius:30, marginBottom:20, marginLeft:20, marginRight:20}}></TextInput>
<TouchableOpacity style={{ backgroundColor: 'chocolate', height:40, width:50, borderRadius:10, marginBottom:20}} onPress={this.pushAdd}></TouchableOpacity>
</View>
</View>
);
}
};
export default App;
我已经用评论 'main problem' 指出了有问题的行。增加和减少按钮不起作用,当我在应用程序中按下它们时,文本中的数字保持不变。我应该对增加和减少按钮的 onPress 方法执行什么更改才能使它们工作?
在 React 中,您不能直接操作数据(就像您在 +/- 按钮 onPress 方法中所做的那样)。这不会有任何效果,相反,您需要使用 setState
适当地更改状态
最快的解决方法是改变
// this
renderListItem = ({item}) => {
// to this
renderListItem = ({item, index}) => {
了解渲染项目的索引。然后,将这些项目内的 increment/decrement 按钮的 onPress
方法更改为使用 setState
而不是
// from this
onPress={()=> item={name:item.name, counter:item.counter + 1}}
// to this
onPress={() =>
this.setState({
task_array: this.state.task_array
.map((item, itemIndex) =>
itemIndex !== index
? item
: {
...item,
counter: item.counter + 1
})
})}
这里发生的是我们使用数组的 .map() 方法从旧的创建一个新的 task_array,除了被点击的一个元素之外,每个元素都保持不变 - 我们通过比较索引来定义.在这种情况下,我们增加它的计数器并使用 this.setState
将新值分配给 task_array
Max的回答是一种实现方式,但是性能不好,每次child update,all view重新渲染一次。
这是我的解决方案:
首先,在父组件中注册一个事件,接收子组件更新通知。
class App extends Component {
constructor(props) {
super(props);
this.state = {
task: "",
task_array: [],
};
}
// register the event,
componentDidMount() {
DeviceEventEmitter.addListener('itemUpdate', this.updateData)
}
componentWillUnmount () {
DeviceEventEmitter.removeListener('ModalVisible', this.updateData)
}
updateData = (params) => {
let copyTaskArray = {...this.state.task_array}
copyTaskArray[params.index].counter = params.counter
this.state.task_array = copyTaskArray
}
然后我们应该将 FlatList Item 移动到单个组件中,并让它更新值
import React,{Component} from 'react';
import { View, TouchableOpacity,DeviceEventEmitter} from 'react-native';
export default class Item extends Component{
constructor(props) {
super(props);
this.state = {
counter:this.props.item.counter
};
}
plus = () => {
let oldCounter = this.state.counter;
let newCounter = oldCounter +1;
this.setState({
counter: newCounter
})
// notify the parent
DeviceEventEmitter.emit("itemUpdate",{index:this.props.index,counter:this.state.counter})
}
reduce = () => {
// the same with plus, only oldCounter -1
}
render() {
return(
<View key={this.props.index} style={{flexDirection: 'row'}}>
<ListItem title={this.props.item.name} style={{width:'75%', marginLeft:20}}></ListItem>
<View style={{flexDirection:'row'}}>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50}} onPress={this.plus}>
<Text>+</Text>
</TouchableOpacity>
<Text>{his.props.item.counter}</Text>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50 }} onPress={this.reduce}>
<Text>-</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
在这种情况下,当项目滚动到屏幕上并重新创建时,该值仍然存在。
最后,我们应该更改父项目的 renderListItem 方法。
renderListItem = ({item, index}) => {
return(
<Item index={index} item={item} ></Item>
);
}
希望对您有所帮助
我编写了一个 Android 应用程序,它由一个 TextInput、一个 Button 和一个 FlatList 组成。对于在 TextInput 中写入的每个名称,平面列表中都会有一个项目。项目标题将是 TextInput 内容,列表项目旁边将有两个按钮和一个文本。一个按钮用于将 Text 显示的数字增加 1,另一个按钮用于减少。这是我的代码:
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
FlatList,
TouchableOpacity,
} from 'react-native';
import { ListItem, SearchBar} from 'react-native-elements';
class App extends Component {
constructor(props) {
super(props);
this.state = {
task: "",
task_array: [],
};
}
ChangeText = (some_task) => {
this.setState({task: some_task});
};
pushAdd = () => {
let contact = {
name: this.state.task,
counter: 0,
};
this.setState({task_array: [...this.state.task_array, contact]});
};
renderListItem = ({item}) => {
return(
<View style={{flexDirection: 'row'}}>
<ListItem title={item.name} style={{width:'75%', marginLeft:20}}></ListItem>
<View style={{flexDirection:'row'}}>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50}} onPress={()=> item={name:item.name, counter:item.counter + 1}}><Text>+</Text></TouchableOpacity>
<Text>{item.counter}</Text>
//main problem <TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50 }} onPress={() => item = { name: item.name, counter: item.counter - 1 }}><Text>-</Text></TouchableOpacity>
</View>
</View>
);
};
render() {
return(
<View style={{ backgroundColor: 'mediumturquoise', width:'100%', height:'100%'}}>
<FlatList
data = {this.state.task_array}
renderItem = {this.renderListItem}
keyExtractor = {(item) => item.name}>
</FlatList>
<View style = {{flexDirection : 'row', alignContent:'center', alignItems:'center'}}>
<TextInput onChangeText={this.ChangeText} style={{ backgroundColor: 'burlywood', height:50, width:'75%', borderRadius:30, marginBottom:20, marginLeft:20, marginRight:20}}></TextInput>
<TouchableOpacity style={{ backgroundColor: 'chocolate', height:40, width:50, borderRadius:10, marginBottom:20}} onPress={this.pushAdd}></TouchableOpacity>
</View>
</View>
);
}
};
export default App;
我已经用评论 'main problem' 指出了有问题的行。增加和减少按钮不起作用,当我在应用程序中按下它们时,文本中的数字保持不变。我应该对增加和减少按钮的 onPress 方法执行什么更改才能使它们工作?
在 React 中,您不能直接操作数据(就像您在 +/- 按钮 onPress 方法中所做的那样)。这不会有任何效果,相反,您需要使用 setState
最快的解决方法是改变
// this
renderListItem = ({item}) => {
// to this
renderListItem = ({item, index}) => {
了解渲染项目的索引。然后,将这些项目内的 increment/decrement 按钮的 onPress
方法更改为使用 setState
而不是
// from this
onPress={()=> item={name:item.name, counter:item.counter + 1}}
// to this
onPress={() =>
this.setState({
task_array: this.state.task_array
.map((item, itemIndex) =>
itemIndex !== index
? item
: {
...item,
counter: item.counter + 1
})
})}
这里发生的是我们使用数组的 .map() 方法从旧的创建一个新的 task_array,除了被点击的一个元素之外,每个元素都保持不变 - 我们通过比较索引来定义.在这种情况下,我们增加它的计数器并使用 this.setState
Max的回答是一种实现方式,但是性能不好,每次child update,all view重新渲染一次。
这是我的解决方案:
首先,在父组件中注册一个事件,接收子组件更新通知。
class App extends Component {
constructor(props) {
super(props);
this.state = {
task: "",
task_array: [],
};
}
// register the event,
componentDidMount() {
DeviceEventEmitter.addListener('itemUpdate', this.updateData)
}
componentWillUnmount () {
DeviceEventEmitter.removeListener('ModalVisible', this.updateData)
}
updateData = (params) => {
let copyTaskArray = {...this.state.task_array}
copyTaskArray[params.index].counter = params.counter
this.state.task_array = copyTaskArray
}
然后我们应该将 FlatList Item 移动到单个组件中,并让它更新值
import React,{Component} from 'react';
import { View, TouchableOpacity,DeviceEventEmitter} from 'react-native';
export default class Item extends Component{
constructor(props) {
super(props);
this.state = {
counter:this.props.item.counter
};
}
plus = () => {
let oldCounter = this.state.counter;
let newCounter = oldCounter +1;
this.setState({
counter: newCounter
})
// notify the parent
DeviceEventEmitter.emit("itemUpdate",{index:this.props.index,counter:this.state.counter})
}
reduce = () => {
// the same with plus, only oldCounter -1
}
render() {
return(
<View key={this.props.index} style={{flexDirection: 'row'}}>
<ListItem title={this.props.item.name} style={{width:'75%', marginLeft:20}}></ListItem>
<View style={{flexDirection:'row'}}>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50}} onPress={this.plus}>
<Text>+</Text>
</TouchableOpacity>
<Text>{his.props.item.counter}</Text>
<TouchableOpacity style={{ backgroundColor: 'blueviolet', height: 20, width: 20, borderRadius: 50 }} onPress={this.reduce}>
<Text>-</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
在这种情况下,当项目滚动到屏幕上并重新创建时,该值仍然存在。
最后,我们应该更改父项目的 renderListItem 方法。
renderListItem = ({item, index}) => {
return(
<Item index={index} item={item} ></Item>
);
}
希望对您有所帮助