javascript - 从孩子改变父母的状态时,为什么父母不再渲染?
问题描述
我有一个父类,它将一个调用的函数传递editClassInfo
给子类。此函数绑定到父级,并且在调用时会不可变地更改父级的状态。但是,父级不会再次渲染,而是必须从父级内部设置状态。
具体来说,问题出在模态组件上textInput
,当文本更改时,它会设置父屏幕的状态。但是,当模态框关闭时,即使状态发生了变化,屏幕的状态也不会立即更新。相反,this.setState()
必须调用另一个才能再次进行渲染。
这是问题的图片参考: https ://imgur.com/a/oCHRTIu
这是代码:
这是父组件。
export default class Classes extends Component {
static navigationOptions = {
title: 'Classes'
};
constructor() {
super();
this.state = {
numObjects: 3.,
classes: [
{
className: "Math",
teacherName: "Someone",
},
{
className: "Science",
teacherName: "Someone",
},
{
className: "Art",
teacherName: "Someone",
}
]
};
this.editClassInfo = this.editClassInfo.bind(this);
}
editClassInfo(index, infoType, value) {
let newClass = this.state.classes;
switch (infoType) {
case 'className':
newClass[index].className = value;
break;
case 'teacherName':
newClass[index].teacherName = value;
break;
}
this.setState({classes: newClass});
}
addClass(name, name2) {
let newClass = this.state.classes.concat({className: name, teacherName: name2});
this.setState({classes: newClass});
}
loadClasses = () => {
this.setState({
numObjects: this.state.numObjects * 2,
})
}
render(){
const classData = this.state.classes;
console.log(this.state.classes[0]);
return (
<View style={styles.container}>
<TopBar title='Classes'/>
<View style={styles.classHeader}>
<Text style={styles.currentClasses}> CURRENT CLASSES </Text>
<TouchableOpacity onPress={() => {this.addClass('World History', 'Someone')}}>
<Image
style = {styles.addClass}
source={require('../resources/addClass.png')}
/>
</TouchableOpacity>
</View>
<FlatList
data = { classData }
onEndReached = {this.loadClasses}
keyExtractor = {(item, index) => index.toString()}
initialNumtoRender = {3}
renderItem = {({item}) =>
<ClassBox
index={this.state.classes.indexOf(item)}
editClassInfo ={this.editClassInfo}
className={item.className}
teacherName={item.teacherName}
/>
}
/>
</View>
);
}
}
我传递editClassInfo
到一个名为ClassBox
:
export default class ClassBox extends Component {
static propTypes = {
className: PropTypes.string.isRequired,
teacherName: PropTypes.string.isRequired,
index: PropTypes.number.isRequired
};
constructor(props) {
super(props);
this.state = {
isVisible: false,
};
this.modalVisible = this.modalVisible.bind(this);
}
modalVisible(visible) {
this.setState({isVisible: visible});
}
render(){
return(
<View>
<ClassEdit
index={this.props.index}
editClassInfo={this.props.editClassInfo}
isVisible={this.state.isVisible}
modalClose={this.modalVisible}
className={this.props.className}
teacherName={this.props.teacherName}
/>
<TouchableOpacity onPress={() => {this.modalVisible(true)}}>
<View style={styles.container}>
<Image
source={{uri: 'http://via.placeholder.com/50x50'}}
style={styles.classImage}
/>
<View style={styles.classInfo}>
<Text style={styles.className}>
{this.props.className}
</Text>
<Text style={styles.teacherName}>
{this.props.teacherName}
</Text>
</View>
</View>
</TouchableOpacity>
</View>
)
}
}
该组件包含 Child Modal ClassEdit
:
export default class ClassEdit extends Component {
static propTypes = {
index: PropTypes.number.isRequired,
isVisible: PropTypes.bool.isRequired,
className: PropTypes.string.isRequired,
teacherName: PropTypes.string.isRequired
}
render() {
return(
<Modal
animationType="none"
transparent={false}
visible={this.props.isVisible}
>
<View style={styles.container}>
<View style={styles.closeTop}>
<TouchableOpacity onPress={() => {
this.props.modalClose(false);
}}>
<Image
style={styles.closeIcon}
source={require('../resources/close.png')}
/>
</TouchableOpacity>
</View>
<View style={styles.classInfo}>
<Image
source={{uri: 'http://via.placeholder.com/150x150'}}
style={styles.classImage}
/>
<TextInput
style={styles.className}
placeholder='Class Name'
value={this.props.className}
onChangeText = {(className) => {this.props.editClassInfo(this.props.index, 'className', className)}}
/>
<TextInput
style={styles.teacherName}
placeholder='Teacher Name'
value={this.props.teacherName}
onChangeText = {(teacherName) => {this.props.editClassInfo(this.props.index, 'teacherName', teacherName)}}
/>
</View>
</View>
</Modal>
);
}
}
正是在最后一个称为ClassEdit
父状态的组件中,当模式关闭时,更新的状态是看不到的,而是必须调用addClass
来触发它。
我对 react-native 有点陌生,所以我的代码可能不是最好的,问题可能非常简单,但任何帮助都将不胜感激。
解决方案
let newClass = this.state.classes;
创建对实际classes
状态的引用,然后您将对其进行变异。
要以不可变的方式创建一个新数组,您可以这样做:
ES6:
let newClass = [...this.state.classes];
ES5:
let newClass = [].concat(this.state.classes);
推荐阅读
- primefaces - jsPDF不导出图形
- java - 谷歌街景api现在使用订阅方式吗?
- business-intelligence - 是否有类似 METABASE 的具有时间序列功能的数据可视化工具?
- firebase - 如何使用 Firestore Rest API runquery 查询特定文档
- javascript - 如果一个键值相同,需要合并两个对象数组
- android - xml 中的 Android Studio 建议未针对特定项目显示
- python - 如何根据用户在运行时选择的逻辑创建新的 pandas 列
- node.js - socket.io 出现错误:“意外的令牌......”
- python - 在for循环中将多个数字相除
- facebook - 使用 facebook 登录返回无效的应用程序 ID