如何创建多个Popper实例?map循环致Tooltip定位失效求助
问题原因分析
你的问题出在RefTooltip组件缺少**componentDidMount生命周期钩子**,导致组件第一次挂载时无法初始化Popper实例,而map渲染的场景刚好触发了这个遗漏的逻辑。
具体细节:
- 当你单独使用
RefTooltip时,大概率是先渲染组件,之后才通过某种方式(比如异步获取ref)更新targetElement属性,这时候componentDidUpdate会被触发,调用reposition方法创建Popper实例,所以定位正常。 - 但在
map渲染的场景中:- 当
<span>挂载后,handleRef被调用,更新state.ref数组 - React会立即渲染
RefTooltip组件,并且在挂载时就已经传入了完整的targetElement属性 - 由于你的组件没有
componentDidMount钩子,第一次挂载时不会执行reposition,Popper实例从未被创建,自然失去定位效果
- 当
修复方案
给RefTooltip组件添加componentDidMount钩子,在组件挂载时就初始化Popper:
export class RefTooltip extends Component<RefTooltipProps> { private ref = createRef(); private popperInstance?: Instance; // 添加这个钩子! componentDidMount() { this.reposition(this.props.targetElement); } componentWillUnmount() { this.destroy(); } componentDidUpdate(prevProps: RefTooltipProps) { const nextProps = this.props; if (prevProps.targetElement !== nextProps.targetElement) { this.reposition(nextProps.targetElement); } } // ... 其余代码保持不变 }
额外优化建议
- 你的
handleRef方法里,每次setState({ ref: [elem] })会把数组重置为只有当前元素,这可能和你“演示多个Tooltip”的需求不符,如果要支持多个元素,应该改为:
handleRef = (elem) => { if (!elem || this.state.ref.some(x => x === elem)) return; this.setState(prev => ({ ref: [...prev.ref, elem] })); }
- 使用
idx作为key在列表渲染中是不推荐的,最好给每个目标元素一个唯一标识,用标识作为key。
内容的提问来源于stack exchange,提问作者Uri Kutner
相关产品推荐
相关产品推荐

