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

React-Native中Pressable onPress无法获取最新useState状态求助

问题分析

你遇到的确实是React闭包陷阱导致的问题:handleAddTransaction函数在组件初始渲染时创建,捕获了当时的name和amount状态值;后续状态更新触发组件重新渲染时,虽然会生成新的handleAddTransaction函数,但如果Pressable组件没有正确更新它的onPress回调绑定,点击时就会调用旧的函数,从而读取到旧的状态值——而输入框因为直接绑定了最新的state,所以显示正常。

解决方案

下面是几种可行的解决方法:

方法1:用useCallback包裹回调函数

通过useCallback将handleAddTransaction与name、amount绑定,确保状态更新时生成新的回调函数,让Pressable能获取到最新的版本:

import { useCallback } from 'react';

const ManualTransactionPage = ({ tabId }: {tabId: string}) => {
  const [name, setName] = useState<string>("Kfc");
  const [amount, setAmount] = useState<string>("15");

  useEffect(() => {
    console.log("state", {
      title: name,
      amount,
    });
  }, [name, amount]);

  // 用useCallback包裹,依赖项包含state
  const handleAddTransaction = useCallback(() => {
    console.log("state", {
      title: name,
      amount,
    });
  }, [name, amount]); // 依赖name和amount,状态更新时重新生成函数

  return (
    <View className="pt-5 mx-3">
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={name}
        onChangeText={setName}
        placeholder="KFC"
      />
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={amount}
        onChangeText={setAmount}
        placeholder="9.99"
      />
      <Pressable
        onPress={handleAddTransaction}
        className="flex flex-row justify-center mt-5 group"
      >
        <ButtonStyling>
          <Text className="text-white text-xl px-3">Add</Text>
        </ButtonStyling>
      </Pressable>
    </View>
  );
};

方法2:用useRef保存最新状态

将状态值存入ref,确保回调能直接读取到最新的引用值:

import { useRef } from 'react';

const ManualTransactionPage = ({ tabId }: {tabId: string}) => {
  const [name, setName] = useState<string>("Kfc");
  const [amount, setAmount] = useState<string>("15");
  
  // 创建ref保存最新状态
  const latestState = useRef({ name, amount });

  // 状态更新时同步ref的值
  useEffect(() => {
    latestState.current = { name, amount };
    console.log("state", {
      title: name,
      amount,
    });
  }, [name, amount]);

  const handleAddTransaction = () => {
    // 直接读取ref的当前值
    console.log("state", latestState.current);
  };

  return (
    <View className="pt-5 mx-3">
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={name}
        onChangeText={setName}
        placeholder="KFC"
      />
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={amount}
        onChangeText={setAmount}
        placeholder="9.99"
      />
      <Pressable
        onPress={handleAddTransaction}
        className="flex flex-row justify-center mt-5 group"
      >
        <ButtonStyling>
          <Text className="text-white text-xl px-3">Add</Text>
        </ButtonStyling>
      </Pressable>
    </View>
  );
};

方法3:直接在onPress中内联逻辑

跳过单独的回调函数,直接在Pressable的onPress里写逻辑,这样每次渲染都会绑定最新的状态:

const ManualTransactionPage = ({ tabId }: {tabId: string}) => {
  const [name, setName] = useState<string>("Kfc");
  const [amount, setAmount] = useState<string>("15");

  useEffect(() => {
    console.log("state", {
      title: name,
      amount,
    });
  }, [name, amount]);

  return (
    <View className="pt-5 mx-3">
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={name}
        onChangeText={setName}
        placeholder="KFC"
      />
      <TextInput
        className="w-full bg-white rounded-xl text-2xl mb-4 px-3 py-4"
        value={amount}
        onChangeText={setAmount}
        placeholder="9.99"
      />
      <Pressable
        onPress={() => {
          console.log("state", {
            title: name,
            amount,
          });
        }}
        className="flex flex-row justify-center mt-5 group"
      >
        <ButtonStyling>
          <Text className="text-white text-xl px-3">Add</Text>
        </ButtonStyling>
      </Pressable>
    </View>
  );
};
验证说明

这几种方法都能解决闭包导致的旧状态读取问题,你可以根据自己的代码习惯选择。其中useCallback是最符合React Hooks规范的方式,能保证回调函数仅在依赖项变化时更新;useRef适合需要在多个地方读取最新状态的场景;内联逻辑则是最简单直接的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:03:17