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>
相关推荐
aiguangyuan4 小时前
浅谈 React Hooks
react·前端开发
whatever who cares2 天前
React hook之userReducer
react.js·react
aiguangyuan2 天前
React Hooks 基础指南
react·前端开发
aiguangyuan3 天前
React 项目初始化与搭建指南
react·前端开发
aiguangyuan3 天前
React 组件异常捕获机制详解
react·前端开发
aiguangyuan3 天前
深入理解 JSX:React 的核心语法
react·前端开发
aiguangyuan4 天前
React 基础语法
react·前端开发
aiguangyuan5 天前
React 核心概念与生态系统
react·前端开发
aiguangyuan5 天前
React 18 生命周期详解与并发模式下的变化
react·前端开发
linweidong13 天前
汇量科技前端面试题及参考答案
webpack·vue3·react·前端面试·hooks·懒加载·flex布局