react 子组件调用父组件方法,获取的数据不是最新值
出现问题的代码如下:
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, 这样每次父组件触发刷新,就会刷新子组件
// 如果点击的事件不会导致父组件刷新,从而刷新子组件
const onBtnClick = _.debounce(onClick, 1000, {
leading: true,
trailing: false,
});
但这种方式只适用于一种情况:点击事件的处理不会导致父组件刷新;
如果父组件刷新,就会导致子组件刷新,从而 debounce
又新建,导致防抖无效。
如果想父组件刷新,子组件不刷新,可以父组件函数onBtnsClick
用useCallback
包裹,Child
组件用memo
包裹
完整代码如下:
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>
<div>
<Child onClick={onBtnsClick} />
);
};
const Child = memo(({ onClick }) => {
const onBtnClick = _.debounce(onClick, 1000, {
leading: true,
trailing: false,
});
return <button onClick={onBtnClick}>子组件</button>;
});
方法二、或者通过监听 val,val 值改变来刷新函数
const onBtnClick2 = useCallback(
_.debounce(onClick, 1000, { leading: true, trailing: false }),
[val]
);
方法三、在父组件中,把 val 作为 key 值,每次 val 变化强制触发更新
这个改动是最小的
<Child key={val} onClick={onBtnsClick} />
// 或者
<div key={val}>
<Child onClick={onBtnsClick} />
</div>