我有一个大问题。我有一个屏幕,它从另一个屏幕接收一些道具,我通过<TicketDiaryHour {...this.props} />
将这些道具传递到该屏幕的组件中。我在 componentDidMount()方法中将元件中的道具设置为我的状态。
在该组件(TicketDiaryHour)中,我也有一个列表。我的问题是我更改了平面列表中的数据(通过setState),而props也正在更改...我不知道为什么会这样。
我的componentDidUpdate()返回prevProps == this.props,还返回prevState == this.state。我不知道为什么...
看:
Prev props: {"navigation":{"state":{"params":{"props":{"id":"418103","headingText":"Klavir","roomText":"Mala dvorana","student":"Ives Berlovčnik","apsent":"1/1","startTime":"07:00","endTime":"07:30","finished":"0","listOfStudents":[{"nameLastname":"Ives Berlovčnik","id":"43275","checked":false,"o":true,"n":false}],"minutes":"30","notes":"","lesson":""}}}
This props: {"navigation":{"state":{"params":{"props":{"id":"418103","headingText":"Klavir","roomText":"Mala dvorana","student":"Ives Berlovčnik","apsent":"1/1","startTime":"07:00","endTime":"07:30","finished":"0","listOfStudents":[{"nameLastname":"Ives Berlovčnik","id":"43275","checked":false,"o":true,"n":false}],"minutes":"30","notes":"","lesson":""}}}
组件代码: 单位列表;
<FlatList
ref={(list) => this.myList = list}
style={[styles.flatList,{height: this.state.height}]}
data={this.state.data}
scrollEnabled = {this.state.showList ? true : false}
contentContainerStyle={{ padding: 15 }}
renderItem={({ item }) => (
<View style={styles.listItemStyle}>
<View style={{flexDirection: 'row', marginBottom: 7, }}>
{
item.checked &&
<TouchableOpacity
onPress={this.changeCheckedToFalse.bind(this,item)}>
<View style={styles.checked} />
</TouchableOpacity> ||
<TouchableOpacity
onPress={this.changeCheckedToTrue.bind(this,item)}>
<View style={styles.unchecked} />
</TouchableOpacity>
}
<Text style={{color: '#000', opacity: 0.6}}>{item.nameLastname}</Text>
{
item.checked &&
<View style={{position: 'absolute', right: 0 }}>
<View style={{flexDirection: 'row'}} >
{
item.o &&
<TouchableOpacity
style={[styles.touchable1Ch,styles.iconStyle1]}
onPress={this.changeSelectionO.bind(this,item)}>
<Text style={{color: '#fff', fontSize: 18, alignSelf: 'center' }}>O</Text>
</TouchableOpacity> ||
<TouchableOpacity
style={[styles.touchable1,styles.iconStyle1]}
onPress={this.changeSelectionO.bind(this,item)}>
<Text style={{color: '#fff', fontSize: 15, alignSelf: 'center' }}>O</Text>
</TouchableOpacity>
}
{
item.n &&
<TouchableOpacity
style={[styles.touchable2Ch,styles.iconStyle1]}
onPress={this.changeSelectionN.bind(this,item)}>
<Text style={{color: '#fff', fontSize: 18, alignSelf: 'center' }}>N</Text>
</TouchableOpacity> ||
<TouchableOpacity
style={[styles.touchable2,styles.iconStyle1]}
onPress={this.changeSelectionN.bind(this,item)}>
<Text style={{color: '#fff', fontSize: 15, alignSelf: 'center' }}>N</Text>
</TouchableOpacity>
}
</View>
</View>
}
</View>
{
this.props.navigation.state.params.props.listOfStudents !== undefined && this.props.navigation.state.params.props.listOfStudents.length >= 2 ?
<View style={styles.line} /> : <Text></Text>
}
</View>
)}
keyExtractor={item => item.id}
/>
我如何在该组件中加载数据:
componentDidMount() {
this.setState({
data: this.props.navigation.state.params.props.listOfStudents,
textOpombe: this.props.navigation.state.params.props.notes,
textVsebinaUre: this.props.navigation.state.params.props.lesson,
finished: this.props.navigation.state.params.props.finished,
absent: parseInt(this.props.navigation.state.params.props.apsent.substring(0,1)),
});
}
如何更改单位列表中的数据;
changeCheckedToFalse = (item) => {
console.log('Item');
var arr = this.state.data;
var indexOfItem = arr.indexOf(item);
arr[indexOfItem].checked = false;
var abs = this.state.absent;
abs -= 1;
this.setState({
data: arr,
//scrollingParent: false,
//scrollingChild: true,
absent: abs,
});
console.log('State after changing: ' + JSON.stringify(this.state.data));
}
最后的代码;更改清单列表项时,将触发此方法
componentDidUpdate(prevProps, prevState) {
console.log('Prev props: ' + JSON.stringify(prevProps));
console.log('This props: ' + JSON.stringify(this.props));
console.log('Prev state: ' + JSON.stringify(prevState));
}
答案 0 :(得分:1)
在我看来,您实际上是在突变this.state.data
/ this.props.navigation.state.params.props.listOfStudents
-因为它们是相同的。
我想您要包括以下行:var arr = this.state.data;
,以便复制this.state.data
中的值,但是恐怕它对于引用类型(例如数组)不起作用)。 arr
实际上指向与this.state.data
完全相同的数组,而this.state.data
指向与this.props...listOfStudents
完全相同的数组
因此,当您更改值时:arr[indexOfItem].checked = false;
实际上是在改变道具。
React的一项非常重要的规则是“不要变异任何东西”,那么您将如何解决这个问题?
最简单的方法是在更改数组之前正确复制该数组:
使用点差运算符
var arr = [...this.state.data];
或使用Array.prototype.slice
方法
var arr = this.state.data.slice()
编辑:尽管上面的描述是正确的,并且如果您有一组原语可以解决您的问题,但实际上您有一组对象引用,这些对象引用与上述问题完全相同。< / p>
复制数组不会复制内部对象,而只会复制对这些对象的引用,因此您会遇到相同的问题。尝试对数组进行深层复制:
var arr = this.state.data.map(x => ({...x}));
或者仅复制您要更改的对象:
var arr = [...this.state.data];
var indexOfItem = arr.indexOf(item);
arr[indexOfItem] = {...item, checked: false};
答案 1 :(得分:0)
您为什么说道具变了?您在问题中指定的prevProps和this.props相同。使用setState方法时,将更新组件,从而触发componentDidUpdate生命周期方法运行。这并不意味着您的道具已经改变。