react 子组件调用父组件方法,获取的数据不是最新值

目录

      • 原因
      • 解决方法
          • [方法一、去掉 useCallback, 这样每次父组件触发刷新,就会刷新子组件](#方法一、去掉 useCallback, 这样每次父组件触发刷新,就会刷新子组件)
          • [方法二、或者通过监听 val,val 值改变来刷新函数](#方法二、或者通过监听 val,val 值改变来刷新函数)
          • [方法三、在父组件中,把 val 作为 key 值,每次 val 变化强制触发更新](#方法三、在父组件中,把 val 作为 key 值,每次 val 变化强制触发更新)

出现问题的代码如下:

typescript 复制代码
const Parent: React.FC = () => {
  const [val, setVal] = useState(0);

  const onBtnsClick = () => {
    console.log(val);
  };

  return (
    <div>
      {val}
      <button onClick={() => setVal(val => val + 1)}>加一</button>
      <Child onClick={onBtnsClick} />
    </div>
  );
};

const Child: React.FC<{ onClick: () => void }> = ({ onClick }) => {
  // useCallback + 防抖
  const onBtnClick = useCallback(
    _.debounce(onClick, 1000, { leading: true, trailing: false }),
    []
  );
  return <button onClick={onBtnClick}>子组件</button>;
};

原因

父组件状态的变更没有引起该子组件中的onBtnClick重新生成,导致方法中的 val 为一开始传入的数值0

解决方法

想办法触发组件刷新,使onBtnsClick 中打印的 val 永远是最新的值

方法一、去掉 useCallback, 这样每次父组件触发刷新,就会刷新子组件
js 复制代码
// 如果点击的事件不会导致父组件刷新,从而刷新子组件
const onBtnClick = _.debounce(onClick, 1000, {
  leading: true,
  trailing: false,
});

但这种方式只适用于一种情况:点击事件的处理不会导致父组件刷新;

如果父组件刷新,就会导致子组件刷新,从而 debounce 又新建,导致防抖无效。

如果想父组件刷新,子组件不刷新,可以父组件函数onBtnsClickuseCallback包裹,Child组件用memo包裹

完整代码如下:

js 复制代码
const Test: React.FC = () => {
  const [val, setVal] = useState(0);
  const onBtnsClick = useCallback(() => {
    console.log(val);
    setVal(val => val + 2)
  }, [val]);

  return (
    <div>
      {val}
      <button onClick={() => setVal(val => val + 1)}>加一</button>
      <Child onClick={onBtnsClick} />
  );
};

const Child = memo(({ onClick }) => {
  const onBtnClick = _.debounce(onClick, 1000, {
    leading: true,
    trailing: false,
  });
  return <button onClick={onBtnClick}>子组件</button>;
});
方法二、或者通过监听 val,val 值改变来刷新函数
js 复制代码
const onBtnClick2 = useCallback(
  _.debounce(onClick, 1000, { leading: true, trailing: false }),
  [val]
);
方法三、在父组件中,把 val 作为 key 值,每次 val 变化强制触发更新

这个改动是最小的

js 复制代码
<Child key={val} onClick={onBtnsClick} />

// 或者
<div key={val}>
  <Child  onClick={onBtnsClick} />
</div>
相关推荐
ai超级个体5 小时前
前端唯一的护城河?结合 AI 将字节组件库 Headless 化后的感想~
前端·react·ai编程·ant design·组件库·vibe coding
白鳯1 天前
塔罗神谕:星月神域莱诺薇为您占卜
react·web·three.js·codex·deepseek·vibe coding·塔罗占卜
CAE虚拟与现实1 天前
前后端调试常用工具大全
前端·后端·vue·react·angular
书到用时方恨少!2 天前
提示词工程终章:ReAct——让大模型“边想边做”的智能体革命
prompt·agent·react·智能体·提示词工程
suixinm3 天前
Agent 设计模式:从 ReAct、CodeAct 到 Agentic Rag 与多智能体
设计模式·ai·react·rag·ai agent·agent智能体·multi-agent
研究点啥好呢4 天前
面馆开业!客官,你的面(经)好了!
python·阿里云·docker·面试·reactjs·求职招聘·react
1104.北光c°7 天前
【AI核心概念讲解】一口气搞懂 Agent:干翻传统后端!自主循环决策的秘密,ReAct 与 Plan-and-Execute 范式
java·人工智能·程序人生·ai·agent·react·智能体
DevilSeagull9 天前
电脑上安装的服务会自动消失? 推荐项目: localhostSCmanager. 更好管理你的服务!
测试工具·安全·react·vite·localhost·hono·trpc
钛态10 天前
前端TypeScript高级技巧:让你的代码更安全
前端·vue·react·web
钛态12 天前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web