如何设置数组中特定索引的状态 React Native
How to setState of a particular index in an array React Native
我有一个对象数组,我当前正在映射这些对象以生成按钮。单击时,我希望用户单击的特定按钮的背景颜色更改颜色(我希望它打开,就像一个开关,这样我最终可以保存到异步存储中)。现在,当用户点击时,所有按钮都会改变颜色。我不太确定我应该如何处理 selectMetric 函数中的 this.setState。
import React, {Component} from 'react';
import {View, Text, ScrollView} from 'react-native';
import {Button} from 'react-native-elements';
const RISK_DATA = [
{id: 1, text: 'cats', flag: false, buttonColor: null},
{id: 2, text: 'dogs', flag: false, buttonColor: null},
]
class IssueSelectionScreen extends Component {
state = {flag: false, buttonColor: null}
selectMetric = (index) => {
for (let i=0; i < RISK_DATA.length; i++) {
if (index === (RISK_DATA[i].id - 1)) {
console.log("RISK_DATA:", RISK_DATA[i]); // logs matching id
// ------------------------------------------------------
// Problem setting correct state here:
RISK_DATA[i].buttonColor = this.setState({flag: true, buttonColor: '#03A9F4'})
// this.setState({flag: true, buttonColor: '#03A9F4'})
// this.setState({update(this.state.buttonColor[i], {buttonColor: {$set: '#03A9F4'}}) })
// ----------------------------------------------------------
}
}
}
showMetric() {
return RISK_DATA.map((metric, index) => {
return (
<View key={metric.id}>
<Button
raised
color={'black'}
title={metric.text}
borderRadius={12}
onPress={() => this.selectMetric(index)}
backgroundColor={this.state.buttonColor}
>
{metric.text}
</Button>
<Text>{/* intentionally blank*/} </Text>
</View>
)
})
}
render() {
return(
<ScrollView style={styles.wrapper}>
<View style={styles.issues}>
{this.showMetric()}
</View>
</ScrollView>
);
}
}
const styles = {
issues: {
justifyContent: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
marginTop: 10,
justifyContent: 'space-between',
},
wrapper: {
backgroundColor: '#009688'
}
}
export default IssueSelectionScreen;
所以您的问题的简短答案如下所示:
class IssueSelectionScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: cloneDeep(RISK_DATA),
};
}
selectMetric = (index) => {
const tempData = cloneDeep(this.state.data);
tempData[index].flag = !tempData[index].flag;
this.setState({ data: tempData });
}
showMetric() {
return this.state.data.map((metric, index) => {
// same
})
}
render() {
// same
}
}
它涉及将整个按钮阵列置于状态中,因为这些按钮的状态是可以改变的。您还可以将标志保持为状态数组,并将按钮信息保持为单独的常量
此解决方案使用 cloneDeep(来自 lodash)来防止代码改变对象的状态,但您也可以使用 this.state.data.map
并创建新对象(只要您的对象是嵌套不深)。
如果您使用的是 Redux,列表可能会作为 prop 进入组件,然后 selectMetric 会调度一个操作来更新 Redux 中的标志。
对于其他查看此内容的人 post,上面的回答非常有帮助。要添加一些最后的评论,如果你想让按钮亮起,我添加了一个简单的 if else to selectMetric:
if (tempData[index].flag) {
tempData[index].buttonColor = '#03A9F4';
console.log('tempData true:', tempData);
} else {
tempData[index].buttonColor = null;
console.log('tempData false:', tempData);
}
并更新了 showMetric 中按钮上的背景颜色 属性:
backgroundColor={this.state.data[index].buttonColor}
我有一个对象数组,我当前正在映射这些对象以生成按钮。单击时,我希望用户单击的特定按钮的背景颜色更改颜色(我希望它打开,就像一个开关,这样我最终可以保存到异步存储中)。现在,当用户点击时,所有按钮都会改变颜色。我不太确定我应该如何处理 selectMetric 函数中的 this.setState。
import React, {Component} from 'react';
import {View, Text, ScrollView} from 'react-native';
import {Button} from 'react-native-elements';
const RISK_DATA = [
{id: 1, text: 'cats', flag: false, buttonColor: null},
{id: 2, text: 'dogs', flag: false, buttonColor: null},
]
class IssueSelectionScreen extends Component {
state = {flag: false, buttonColor: null}
selectMetric = (index) => {
for (let i=0; i < RISK_DATA.length; i++) {
if (index === (RISK_DATA[i].id - 1)) {
console.log("RISK_DATA:", RISK_DATA[i]); // logs matching id
// ------------------------------------------------------
// Problem setting correct state here:
RISK_DATA[i].buttonColor = this.setState({flag: true, buttonColor: '#03A9F4'})
// this.setState({flag: true, buttonColor: '#03A9F4'})
// this.setState({update(this.state.buttonColor[i], {buttonColor: {$set: '#03A9F4'}}) })
// ----------------------------------------------------------
}
}
}
showMetric() {
return RISK_DATA.map((metric, index) => {
return (
<View key={metric.id}>
<Button
raised
color={'black'}
title={metric.text}
borderRadius={12}
onPress={() => this.selectMetric(index)}
backgroundColor={this.state.buttonColor}
>
{metric.text}
</Button>
<Text>{/* intentionally blank*/} </Text>
</View>
)
})
}
render() {
return(
<ScrollView style={styles.wrapper}>
<View style={styles.issues}>
{this.showMetric()}
</View>
</ScrollView>
);
}
}
const styles = {
issues: {
justifyContent: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'flex-start',
marginTop: 10,
justifyContent: 'space-between',
},
wrapper: {
backgroundColor: '#009688'
}
}
export default IssueSelectionScreen;
所以您的问题的简短答案如下所示:
class IssueSelectionScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: cloneDeep(RISK_DATA),
};
}
selectMetric = (index) => {
const tempData = cloneDeep(this.state.data);
tempData[index].flag = !tempData[index].flag;
this.setState({ data: tempData });
}
showMetric() {
return this.state.data.map((metric, index) => {
// same
})
}
render() {
// same
}
}
它涉及将整个按钮阵列置于状态中,因为这些按钮的状态是可以改变的。您还可以将标志保持为状态数组,并将按钮信息保持为单独的常量
此解决方案使用 cloneDeep(来自 lodash)来防止代码改变对象的状态,但您也可以使用 this.state.data.map
并创建新对象(只要您的对象是嵌套不深)。
如果您使用的是 Redux,列表可能会作为 prop 进入组件,然后 selectMetric 会调度一个操作来更新 Redux 中的标志。
对于其他查看此内容的人 post,上面的回答非常有帮助。要添加一些最后的评论,如果你想让按钮亮起,我添加了一个简单的 if else to selectMetric:
if (tempData[index].flag) {
tempData[index].buttonColor = '#03A9F4';
console.log('tempData true:', tempData);
} else {
tempData[index].buttonColor = null;
console.log('tempData false:', tempData);
}
并更新了 showMetric 中按钮上的背景颜色 属性:
backgroundColor={this.state.data[index].buttonColor}