如何在 React Native 中使用 AsyncStorage 构建 TextInput

43 阅读3分钟

问题 你有一个房屋详情页面,里面有一个备注字段,但是当用户在 TextInput 中输入内容并点击“保存”时,没有任何反应。备注并没有保存到 AsyncStorage,表单感觉很乱。

这是 React Native 应用程序中的一个常见问题,开发人员使用defaultValue受控组件,或者忘记正确管理本地状态。

解决方案:受控组件 关键是通过使用本地状态管理其值并将其连接到数据持久层,使您的 TextInput 成为受控组件。

步骤 1:了解架构 在深入研究代码之前,让我们先了解一下数据流:

User types → Local State → Save Button → Context → AsyncStorage 本地状态:实时跟踪用户输入的内容 上下文:管理全局状态和持久性 AsyncStorage:实际的存储机制 步骤 2:设置本地状态 首先,您需要使用本地状态跟踪用户的输入:

import { useState, useEffect } from 'react';

export default function HouseDetails() { const [textNotes, setTextNotes] = useState("");

// ... rest of your component

} 为什么要使用本地状态?因为你需要在用户保存之前追踪他们的输入。如果没有本地状态,TextInput 就会“不受控制”,用户的输入也会丢失。

步骤 3:使用现有数据初始化 当组件加载时,您需要使用任何现有注释填充 TextInput:

useEffect(() => { if (house) { setTextNotes(house.notes || ""); } }, [house]); 这确保了如果房子已经有注释,当用户打开屏幕时它们就会出现在 TextInput 中。

步骤 4:控制 TextInput 现在,将您的本地状态连接到 TextInput:

<TextInput placeholder="Enter your notes" value={textNotes} // Controlled by local state onChangeText={setTextNotes} // Updates local state on every keystroke style={styles.notesInput} multiline numberOfLines={4} /> 要点:

value={textNotes}使其受到控制 onChangeText={setTextNotes}每次击键时更新状态 不再是了defaultValue——这是针对不受控制的组件 步骤 5:保存到 AsyncStorage 创建使用您的上下文的保存函数:

const saveNotes = () => { updateHouse(id as string, { notes: textNotes }); router.back(); // Optional: navigate back after saving }; 并将其连接到您的保存按钮:

Save 步骤6:处理身份证件类型问题 由于useLocalSearchParams()可以返回字符串或字符串数​​组,请正确处理:

const saveNotes = () => { const houseId = Array.isArray(id) ? id[0] : id; updateHouse(houseId, { notes: textNotes }); router.back(); }; 完整的解决方案 以下是各个部分的组合方式:

import { useState, useEffect } from 'react'; import { useHouses } from "@/contexts/HousesContext";

export default function HouseDetails() { const { id } = useLocalSearchParams(); const { houses, updateHouse } = useHouses(); const [textNotes, setTextNotes] = useState("");

const house = houses.find(h => h.id === id);

// Initialize with existing notes
useEffect(() => {
    if (house) {
        setTextNotes(house.notes || "");
    }
}, [house]);

// Save function
const saveNotes = () => {
    const houseId = Array.isArray(id) ? id[0] : id;
    updateHouse(houseId, { notes: textNotes });
    router.back();
};

return (
    // ... your JSX
    <TextInput
        placeholder="Enter your notes"
        value={textNotes}
        onChangeText={setTextNotes}
        style={styles.notesInput}
        multiline
        numberOfLines={4}
    />

    <TouchableOpacity onPress={saveNotes}>
        <Text style={styles.saveButton}>Save</Text>
    </TouchableOpacity>
    // ... rest of JSX
);

} 为什么有效 受控组件textNotes:TextInput 值由状态控制 实时更新:onChangeText每次击键时更新状态 持久性:保存函数调用上下文的updateHouse方法 数据流:本地状态 → 上下文 → AsyncStorage 应避免的常见陷阱 ❌不要使用defaultValue- 这会使组件不受控制 ❌不要忘记useEffect- 您需要使用现有数据进行初始化 ❌不要忽略 ID 类型-useLocalSearchParams可以返回数组 ❌不要保存原始注释- 而是保存本地状态值

关键要点 受控组件让您完全控制表单状态 本地状态对于保存之前跟踪用户输入至关重要 useEffect确保现有数据填充表单 正确的类型处理可以防止运行时错误 Context + AsyncStorage提供可靠的持久性 此模式适用于 React Native 中的任何表单字段 - 不仅仅是注释。同样的原则也适用于编辑名称、描述或应用中的任何其他文本输入。

之前与之后 之前(破损) <TextInput defaultValue={notes || "???"} // ❌ Uncontrolled editable={false} // ❌ Can't edit /> 工作后 <TextInput value={textNotes} // ✅ Controlled onChangeText={setTextNotes} // ✅ Updates state // ✅ Editable by default /> 作者www.whatapp.biz