React Native提交日志后State未更新,界面未同步问题求助
问题原因分析
- DateTimePicker的onChange处理不当: 当用户取消日期选择器时,
newDate为undefined,直接设置会导致date状态变为undefined,后续调用toISOString()会抛出错误,中断setState执行。 - 状态更新与导航的时序问题:
setState是异步操作,提交后立即调用navigation.navigate会导致组件在状态更新完成前就被卸载,状态变更无法反映到界面上。
解决方案
1. 修复日期选择器的 onChange 处理
修改setDate方法,仅在用户确认选择日期时更新状态:
setDate = (event, newDate) => { // 仅在用户确认选择日期时更新状态 if (event.type === 'set') { this.setState({ date: newDate }); } };
2. 调整状态更新与提交的顺序
先捕获当前表单数据,清空状态后再执行提交和导航,确保状态更新完成后再触发界面跳转:
postEntry = () => { const { body, date } = this.state; if (body.length === 0) { return; } // 保存当前要提交的数据 const entryToSubmit = { body, date: date.toISOString(), }; // 先清空状态,在回调中执行提交和导航 this.setState({ body: "", date: new Date(), }, () => { this.props.onSubmit(entryToSubmit); Keyboard.dismiss(); }); };
3. 优化布局配置
调整PostScreen的布局方向为column,确保表单正确填充屏幕,避免按钮点击区域异常:
const styles = StyleSheet.create({ container: { flex: 1, flexDirection: "column", }, });
修改后的完整代码
PostForm.js
import React from "react"; import { StyleSheet, View, TextInput, Pressable } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import DateTimePicker from "@react-native-community/datetimepicker"; import { Keyboard } from "react-native"; export default class PostForm extends React.Component { state = { body: "", date: new Date(), }; setBody = (newBody) => { this.setState({ body: newBody }); }; setDate = (event, newDate) => { if (event.type === 'set') { this.setState({ date: newDate }); } }; postEntry = () => { const { body, date } = this.state; if (body.length === 0) { return; } const entryToSubmit = { body, date: date.toISOString(), }; this.setState({ body: "", date: new Date(), }, () => { this.props.onSubmit(entryToSubmit); Keyboard.dismiss(); }); }; render() { return ( <View style={styles.vertContainer}> <View style={styles.horContainer}> <DateTimePicker style={styles.dateTime} value={this.state.date} accentColor="#E2AFDE" onChange={this.setDate} /> <Pressable style={styles.post} onPress={() => this.postEntry()}> <Ionicons style={styles.postIcon} name="arrow-forward-outline" size={30} /> </Pressable> </View> <TextInput style={styles.input} placeholder="What happened?" multiline={true} value={this.state.body} onChangeText={(newText) => this.setBody(newText)} maxLength={378} /> </View> ); } } const styles = StyleSheet.create({ vertContainer: { flex: 1, flexDirection: "column", }, horContainer: { flexDirection: "row", alignItems: "center", paddingTop: 10, paddingRight: 10, justifyContent: "space-between", }, input: { width: "100%", flexWrap: "wrap", padding: 15, fontSize: 20, paddingTop: 10, }, post: { backgroundColor: "#E2AFDE", borderRadius: 10, alignItems: "center", justifyContent: "center", width: 50, height: 50, }, postIcon: { color: "white", }, dateTime: {}, });
PostScreen.js
import React from "react"; import { StyleSheet, View } from "react-native"; import PostForm from "../components/PostForm"; import { connect } from "react-redux"; import { addEntry } from "../redux/actions"; class PostScreen extends React.Component { handleSubmit = (form) => { this.props.addEntry(form); this.props.navigation.navigate("HomeScreen"); }; render() { return ( <View style={styles.container}> <PostForm onSubmit={this.handleSubmit} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, flexDirection: "column", }, }); export default connect(null, { addEntry })(PostScreen);
内容的提问来源于stack exchange,提问作者Daniel Goldenberg
相关产品推荐
相关产品推荐

