使用AsyncStorage存储待办事项时列表无法加载问题求助
问题原因及修复方案
1. 空数组判断逻辑错误
JavaScript中数组是引用类型,todos === []永远返回false,两个不同的数组实例哪怕内容完全一致,引用地址不同就不会相等。
修改方案:改成判断数组长度:
todos.length === 0
2. 新增待办后未更新本地state
你在addItem方法中仅把新的待办数组存入了AsyncStorage,没有调用setTodos更新组件的本地状态,界面自然不会触发重渲染刷新列表。
修改方案:在调用_storeData前新增更新state的逻辑:
let newTodos = [newTodo, ...todos]; setTodo(''); setTodos(newTodos); // 新增这行 _storeData(JSON.stringify(newTodos));
3. useEffect依赖配置错误引发死循环风险
你当前把todos作为useEffect的依赖,每次todos变化都会触发_retrieveData读存储,读出来又调用setTodos修改todos,会陷入无限循环。实际上只需要组件首次挂载时读一次存储初始化数据即可。
修改方案:把useEffect的依赖改成空数组:
useEffect(() => { _retrieveData(); }, []); // 空数组代表仅挂载时执行一次
4. 错误捕获变量名错误
_storeData方法的catch块中,你打印的变量是e,但catch接收的参数名是error,运行时会报变量未定义错误。
修改方案:统一变量名:
catch (error) { console.log(error); }
5. 删除待办未同步到AsyncStorage
deleteTodo方法中仅更新了本地state,没有同步修改AsyncStorage里的数据,下次APP重启后被删除的待办会重新出现。
修改方案:删除后同步更新存储:
const deleteTodo = (idx) => { const newTodos = todos.filter((todo, id) => id !== idx); setTodos(newTodos); _storeData(JSON.stringify(newTodos)); };
完整修正后的代码
export default function App() { const [todo, setTodo] = useState(''); const [todos, setTodos] = useState([]); // 仅挂载时读一次存储初始化数据 useEffect(() => { _retrieveData(); }, []); const addItem = (newTodo) => { if (newTodo.length === 0) { Alert.alert( 'Enter a String', 'You have entered a string with 0 characters', [{ text: 'Okay', style: 'default' }] ); } else { console.log(newTodo); let newTodos = [newTodo, ...todos]; setTodo(''); setTodos(newTodos); // 新增更新本地状态 _storeData(JSON.stringify(newTodos)); } }; const deleteTodo = (idx) => { const newTodos = todos.filter((todo, id) => id !== idx); setTodos(newTodos); _storeData(JSON.stringify(newTodos)); // 同步更新存储 }; const _storeData = async (value) => { try { await AsyncStorage.setItem('TASKS', value); } catch (error) { // 修正变量名 console.log(error); } }; const _retrieveData = async () => { try { const value = await AsyncStorage.getItem('TASKS'); if (value !== null) { setTodos(JSON.parse(value)); console.log(value); } } catch (error) { console.log(error); } }; return ( <TouchableWithoutFeedback onPress={() => { Keyboard.dismiss(); }} > <View style={styles.outerContainer}> <Text style={styles.header}>TODO</Text> <View style={styles.container}> <TextInput placeholder='new todo' style={styles.input} value={todo} onChangeText={(text) => { setTodo(text); }} ></TextInput> <Button title='Add' onPress={() => addItem(todo)}></Button> </View> <ScrollView style={styles.scrollView}> {/* 修正空数组判断逻辑 */} {todos.length === 0 ? ( <View> <Text>Add a todo!</Text> </View> ) : ( todos.map((todo, idx) => ( <View style={styles.todo} key={idx}> <Text style={styles.todoText}>{todo}</Text> <View style={styles.delete}> <Button color='red' title='Delete' onPress={() => deleteTodo(idx)} ></Button> </View> </View> )) )} </ScrollView> </View> </TouchableWithoutFeedback> ); }
内容的提问来源于stack exchange,提问作者Nithin Deepkumar
相关产品推荐
相关产品推荐

