Как создать несколько экземпляров поппера? - PullRequest
1 голос
/ 30 марта 2020

В моем приложении я пытаюсь использовать Popper для создания всплывающей подсказки для каждого элемента в приложении. (Обычно я показываю только одну подсказку, но для презентации я хочу показать больше одной).

Я написал этот компонент Component , чтобы прикрепить подсказку непосредственно к ссылке.

Это работает довольно хорошо, но когда я пытаюсь использовать его внутри [].map(), как обычные компоненты реакции, я теряю все свое позиционирование: https://bit.dev/bit/base/atoms/ref-tooltip?example=5e81d946443f4900195606b7

import React, { Component } from 'react';
import { RefTooltip } from '@bit/bit.base.atoms.ref-tooltip'

export default class ExampleUsage extends Component {
    state = { ref: [] };

    handleRef = (elem) => {
        if (this.state.ref.some(x => x === elem)) return;

        this.setState({ ref: [elem] });
    }

    render() {
        return (
            <div>
                <span ref={this.handleRef}>target</span>

                { /*
                   * (!)
                   * This .map() breaks tooltip
                   *
                   */ }
                {this.state.ref.map((elem, idx) => (
                    <RefTooltip key={idx} targetElement={elem}>
                        "tooltip"
                    </RefTooltip>
                ))}
            </div>
        );
    }
}
//ref-tooltip.tsx
import React, { Component } from 'react';
import classNames from 'classnames';

//@ts-ignore
import createRef from 'react-create-ref';
import { createPopper, Instance, Options } from '@popperjs/core';

import styles from './ref-tooltip.module.scss';

export type RefTooltipProps = {
    targetElement?: HTMLElement;
    popperOptions?: Partial<Options>;
} & React.HTMLAttributes<HTMLDivElement>;

export class RefTooltip extends Component<RefTooltipProps> {
    private ref = createRef();
    private popperInstance?: Instance;

    componentWillUnmount() {
        this.destroy();
    }

    componentDidUpdate(prevProps: RefTooltipProps) {
        const nextProps = this.props;

        if (prevProps.targetElement !== nextProps.targetElement) {
            this.reposition(nextProps.targetElement);
        }
    }

    private reposition = (targetElement?: HTMLElement) => {
        const { popperOptions = popperDefaultOptions } = this.props;
        const popperElement = this.ref.current;

        if (!targetElement) {
            this.destroy();
        }

        if (!targetElement || !popperElement) return;

        this.popperInstance = createPopper(targetElement, popperElement, popperOptions);
    };

    private destroy() {
        if (!this.popperInstance) return;

        this.popperInstance.destroy();
        this.popperInstance = undefined;
    }

    render() {
        const { className, targetElement, ...rest } = this.props;
        return (
            <div
                {...rest}
                ref={this.ref}
                className={classNames(styles.tooltipWrapper, className)}
                data-ignore-component-highlight
            />
        );
    }
}

const popperDefaultOptions: Partial<Options> = {
    placement: 'top',
    modifiers: [
        {
            name: 'flip',
            enabled: false,
        },
    ],
};

Ожидаемый:
enter image description here

Фактический:
enter image description here

Я не понимаю, почему .map () ломает поппер. По крайней мере, для массива 1 он должен вести себя так же. Есть идеи, почему это не работает?

...