You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 20:36:03