在子组件内有:
// 滚动
useEffect(() => {
if(props.scrollToIdx) {
const scrollToIdx = props.scrollToIdx
console.log("滚动ID:", '#item-' + scrollToIdx!.toString())
scrollTo(scrollToIdx)
}
}, [props.scrollToIdx])
const scrollTo = (scrollToIdx: number) => {
const container = document.querySelector("#container")
const div: HTMLDivElement | null = document.querySelector('#item-' + scrollToIdx!.toString())
console.log(container, div)
if(container) {
container.scrollTo({
top: div!.offsetTop,
behavior: 'smooth'
});
}
}
在父组件
点击按钮时候会滑动:
const btnClick = () => {
console.log('点击按钮')
setSelIdx(20)
}
return (
<div className="App">
<SubContainer {...props}></SubContainer>
<button onClick={btnClick}>点击</button>
</div>
);
但是比如我在点击一次setSelIdx(20)之后,再点击,执行:
setSelIdx(20)
子组件就不会更新再继续执行这个代码了:
useEffect(() => {
if(props.scrollToIdx) {
const scrollToIdx = props.scrollToIdx
console.log("滚动ID:", '#item-' + scrollToIdx!.toString())
scrollTo(scrollToIdx)
}
}, [props.scrollToIdx])
也就是说:props.scrollToIdx 没有更新这里就不会执行,请问要如何保证父组件点击(btnClick ... setSelIdx(20))
子组件这里每次都执行?
写 React 大家容易陷入一个误区:所有的功能都得通过 props 实现,props 一般用于响应式的更新。
例如你这个场景,如果 scrollToIdx 变化触发 scrollTo,scrollToIdx 不变不触发,使用 props 传递参数是合适的。
按照你的描述,是希望稳定触发 scrollTo,使用 props 去控制就不合适了,这个时候应该采用命令式调用,而不是响应式更新了。
可以使用 ref:
在父组件调用:
总结一下:响应式更新使用 props,命令式调用使用 ref。