React Native文本输入框输入后恢复初始状态问题解决求助
问题原因及解决方法
核心问题:无依赖的useEffect导致输入被覆盖
你的useEffect未设置依赖数组,这会导致组件每次重新渲染时都会执行_readdiary。当你在TextInput输入内容时,setTitle触发组件渲染,紧接着_readdiary会从AsyncStorage读取旧数据并重置title,最终导致输入框回到初始状态。
具体修复步骤
1. 给useEffect添加正确的依赖数组
修改useEffect,仅在组件初始化或dateString变化时读取数据:
useEffect(() => { _readdiary(); }, [dateString]); // 仅当dateString改变时执行
2. 修复_savediary的状态异步问题
setTitle是异步操作,直接调用setTitle(text)后使用title值存数据,拿到的会是更新前的旧值。应该直接将输入的text作为参数传入:
const handleChangeTitle = (text) => { setTitle(text); _savediary(text); // 直接传递最新输入的text }; const _savediary = async (text) => { try { await AsyncStorage.setItem(dateString + "diary", text); } catch(error) { console.error(error); } };
3. 优化dateString生成逻辑
当前用for in循环遍历day对象,最终dateString只会是对象的最后一个属性值,不符合预期。如果day是包含日期的结构化对象,建议明确取值:
// 示例:假设day包含date属性,根据实际结构调整 const dateString = day.date; // 若需要组合多属性: // const dateString = `${day.year}-${day.month}-${day.day}`;
4. 修复拼写错误
导入语句中的Compomen是拼写错误,直接删除即可(未被使用):
import React, {useState, useEffect} from 'react';
5. 移除冗余的SafeAreaProvider
SafeAreaProvider只需在App根组件中使用一次,无需在每个页面嵌套,建议移除当前组件中的该标签。
修复后的完整代码示例
import React, {useState, useEffect} from 'react'; import {View, TextInput, StyleSheet, Text, TouchableOpacity, Image} from 'react-native'; import AsyncStorage from "@react-native-async-storage/async-storage"; function DetailScreen({ navigation, route }) { const { day } = route.params; const [title, setTitle] = useState(""); // 根据day实际结构调整dateString的生成方式 const dateString = day.date; const handleChangeTitle = (text) => { setTitle(text); _savediary(text); } const _readdiary = async () => { try { const savedText = await AsyncStorage.getItem(dateString + "diary"); if (savedText == null) { setTitle("Write your day here."); } else { setTitle(savedText); } } catch(error) { console.error(error); } }; const _savediary = async (text) => { try { await AsyncStorage.setItem(dateString + "diary", text); } catch(error) { console.error(error); } }; useEffect(() => { _readdiary(); }, [dateString]); return( <View style={{flexDirection: 'column'}}> <View style={{flexDirection: 'row'}}> <Text style={styles.date}> {dateString}</Text> <TouchableOpacity activeOpacity={0.5} onPress={() => navigation.push('Mood', {day})}> <Image source={require('./assets/select.png')} style={styles.sticker} /> </TouchableOpacity> </View> <TextInput style={{padding: 10}} onChangeText={handleChangeTitle} editable multiline value={title} /> </View> ); } const styles = StyleSheet.create({ input_container: { borderWidth: 0.5, padding: 15, fontSize: 16, marginTop: 20, borderRadius: 50, }, date: { fontSize: 30, width: "75%" }, sticker: { height: 50, width: 50, }, center: { flex: 1, alignItems: "center" }, }); export default DetailScreen;
内容的提问来源于stack exchange,提问作者Beom
相关产品推荐
相关产品推荐

