Expo React Native待办应用如何将TextInput值存入本地存储并启动时读取
解决方案
你当前的数据仅存储在React组件的内存状态中,应用关闭后内存会被系统回收,所以数据会丢失,只需要把待办数据持久化存储到本地即可,Expo环境下可以使用expo-secure-store实现本地持久化,操作步骤如下:
步骤1:安装依赖
在项目根目录执行以下命令安装存储库:
npx expo install expo-secure-store
步骤2:修改代码
需要新增三个逻辑:
- 组件首次加载时读取本地存储的历史待办和最大id,初始化状态
- 新增待办时同步更新本地存储
- 删除待办时同步更新本地存储
同时你原有代码中renderItem函数缺少返回值,会导致列表无法正常渲染,已同步修复。
修改后的完整代码如下:
import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, TextInput } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons' import * as SecureStore from 'expo-secure-store'; import Line from './Line'; // 本地存储的key常量 const TODO_STORAGE_KEY = 'todo_list_data'; const MAX_ID_STORAGE_KEY = 'todo_max_id'; function App() { //存储待办数据 const [initialElements, changeEl] = useState([]); const [value, setValue] = useState('') const [idx, incr] = useState(1); const [exampleState, setExampleState] = useState(initialElements); // 组件挂载时读取本地存储的历史数据 useEffect(() => { const initData = async () => { try { const savedTodos = await SecureStore.getItemAsync(TODO_STORAGE_KEY); const savedMaxId = await SecureStore.getItemAsync(MAX_ID_STORAGE_KEY); if (savedTodos) { const todoList = JSON.parse(savedTodos); changeEl(todoList); setExampleState(todoList); } if (savedMaxId) { incr(parseInt(savedMaxId)); } } catch (e) { console.log('读取本地数据失败', e); } } initData(); }, []); // 保存数据到本地的通用方法 const saveToStorage = async (todoList, maxId) => { try { await SecureStore.setItemAsync(TODO_STORAGE_KEY, JSON.stringify(todoList)); await SecureStore.setItemAsync(MAX_ID_STORAGE_KEY, maxId.toString()); } catch (e) { console.log('保存数据到本地失败', e); } } //新增待办逻辑 const addElement = () => { if (value != '') { var newArray = [...initialElements, { id: idx, title: value }]; const newId = idx + 1; incr(newId); setExampleState(newArray); changeEl(newArray); // 同步保存到本地 saveToStorage(newArray, newId); // 清空输入框 setValue(''); } } //删除待办逻辑 const delElement = (id) => { let newArray = initialElements.filter(function (item) { return item.id !== id }) setExampleState(newArray); changeEl(newArray); // 同步更新本地存储 saveToStorage(newArray, idx); } //待办项组件 const Item = ({ title, id }) => ( <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}> <View style={{ borderWidth: 2, margin: 5, flex: 1, padding: 10, borderRadius: 10 }}> <TouchableOpacity onPress={() => { alert(title) }}> <Text >{title}</Text> </TouchableOpacity> </View> <TouchableOpacity onPress={() => delElement(id)}> <MaterialIcons name='delete' size={24} /> </TouchableOpacity> </View> ); //列表渲染逻辑,修复原有缺少返回值的问题 const renderItem = ({ item }) => { return <Item title={item.title} id={item.id} /> } return ( <View style={styles.container}> <View style={{ alignItems: 'center', marginBottom: 10 }}> <Text style={{ fontSize: 20, fontWeight: '500' }}> To <Text style={{ color: 'skyblue', fontWeight: '900' }}>Do</Text> List</Text> <Line /> </View> <View> <TextInput value={value} onChangeText={text => setValue(text)} placeholder="输入待办内容" style={{ borderWidth: 2, borderRadius: 10, backgroundColor: 'skyblue', height: 40, paddingLeft: 10, borderColor: 'black' }}></TextInput> </View> <View style={{ alignItems: 'center' }}> <TouchableOpacity onPress={() => addElement()} style={{ marginTop: 10 }}> <View style={{ backgroundColor: 'black', width: 70, height: 40, justifyContent: 'center', borderRadius: 10 }}> <Text style={{ color: 'white', textAlign: 'center' }}>添加</Text> </View> </TouchableOpacity> </View> <FlatList style={{ borderWidth: 2, padding: 10, flex: 1, backgroundColor: '#EEDDD0', marginTop: 10 }} data={exampleState} renderItem={renderItem} keyExtractor={item => item.id.toString() } /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, marginTop: 20, margin: 5, } }) export default App;
内容的提问来源于stack exchange,提问作者Tanjil Pranto
相关产品推荐
相关产品推荐

