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

React Native中useRef绑定Input值异常:切换下拉框后输入内容清空

问题分析

你遇到的核心问题是错误地使用useRef管理受控输入组件的状态。useRef的特性是值变化不会触发组件重渲染,它主要用于存储DOM引用或无需响应式更新的变量,不适合用来管理需要实时同步的输入值。另外,切换分类时的refInputs重置逻辑存在异步问题,加上初始useEffect中fields的异步更新导致ref初始化错误,最终引发输入内容清空的问题。

解决方案

改用useState管理输入字段的值,让输入组件成为真正的受控组件。具体调整如下:

  1. 新增fieldValues状态,存储每个字段的输入值,结构与fields数组对应。
  2. 初始化和切换分类时,根据当前fields数组初始化fieldValues为空字符串数组。
  3. 调整输入值更新、添加/删除字段的逻辑,基于fieldValues状态而非useRef。
修改后的完整代码
export default function CreateEntry({ navigation }) {
  const { user, setLoading, setLoadingMsg } = useAuthContext();
  const [name, setName] = useState("");
  const [selectedCategory, setSelectedCategory] = useState("");
  const [categoriesList, setCategoriesList] = useState([]);
  const [primary, setPrimary] = useState("");
  const [primaryValue, setPrimaryValue] = useState("");

  const [fields, setFields] = useState([
    {
      name: "Email",
      value: "",
      type: "string",
      encrypt: false,
    },
    {
      name: "Password",
      value: "",
      type: "string",
      encrypt: true,
    },
  ]);
  // 用useState管理输入值,替代useRef
  const [fieldValues, setFieldValues] = useState([]);

  useEffect(() => {
    firestore()
      .collection("categories")
      .doc(user.uid)
      .get()
      .then((documentSnapshot) => {
        const categoryData = documentSnapshot.data().category;
        setCategoriesList(categoryData);
        const initialCategory = categoryData[0];
        setSelectedCategory(initialCategory.name);
        setFields(initialCategory.fields);
        // 初始化输入值数组
        setFieldValues(Array(initialCategory.fields.length).fill(""));
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  // 监听fields变化,同步更新fieldValues的长度(比如切换分类时)
  useEffect(() => {
    setFieldValues(prev => {
      // 如果新fields长度和之前不同,重置为对应长度的空数组
      if (fields.length !== prev.length) {
        return Array(fields.length).fill("");
      }
      return prev;
    });
  }, [fields]);

  const addInput = () => {
    setFields([
      ...fields,
      { name: "First", value: "", type: "string", encrypt: false },
    ]);
    // 添加新字段时,同步添加空值到fieldValues
    setFieldValues([...fieldValues, ""]);
  };

  const removeInput = (i) => {
    // 删除字段时,同步移除对应位置的输入值
    setFields(prevFields => prevFields.filter((_, index) => index !== i));
    setFieldValues(prevValues => prevValues.filter((_, index) => index !== i));
  };

  const setInputValue = (index, value) => {
    setFieldValues(prevValues => {
      const newValues = [...prevValues];
      newValues[index] = value;
      return newValues;
    });
  };

  const inputs = fields.map((field, i) => (
    <View key={i}>
      <TextInput
        onChangeText={(value) => setInputValue(i, value)}
        value={fieldValues[i] || ""}
      />
      <TouchableOpacity onPress={() => removeInput(i)}>
        <Ionicons name="close" style={[tw``]} size={22} color="#ddd" />
      </TouchableOpacity>
    </View>
  ));

  const addEntry = () => {
    // 提交时可以将fields和fieldValues对应起来
    const entryFields = fields.map((field, index) => ({
      ...field,
      value: fieldValues[index]
    }));
    // 后续处理逻辑...
  };

  return (
    <ScrollView style={styles.container}>
      <Dropdown
        data={categoriesList}
        value={selectedCategory}
        onChange={(item) => {
          setSelectedCategory(item.name);
          setFields(item.fields);
          // 切换分类时自动初始化输入值
          setFieldValues(Array(item.fields.length).fill(""));
        }}
      />
  
      <Input
        onChangeText={setName}
        value={name}
        placeholder="Name"
      />

      {inputs}
      <Pressable onPress={addInput}>
        <Text>+ Add a new input</Text>
      </Pressable>

      <MainButton onPress={addEntry}>Add</MainButton>
    </ScrollView>
  );
}
关键修改点说明
  • 用fieldValues这个useState状态替代refInputs,确保输入值的变化能触发组件重渲染,同步更新UI。
  • 添加useEffect监听fields变化,自动同步fieldValues的长度,避免切换分类时出现索引不匹配的问题。
  • 调整addInput、removeInput方法,同步更新fieldValues数组,保证字段和输入值的对应关系。
  • 提交逻辑中可直接将fields和fieldValues合并,得到完整的字段数据。

内容的提问来源于stack exchange,提问作者Rajesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:10:29