问题:无法使用 D3 和 React 在 useEffect 挂钩中进行画笔交互和设置状态

我正在尝试使用 D3 和 React 在时间轴上创建画笔交互,但我不知道为什么它不起作用。

一切似乎都很好,但是当我在useEffect()中设置状态时,index变量会创建一个无限循环。

    const Timeline = () => {
    const svgRef = useRef(null!);
    const brushRef = useRef(null!);
    const x = scaleLinear().domain([0, 1000]).range([10, 810]);
    const [pos, setPos] = useState([]);

    useEffect(() => {
        const svg = select(svgRef.current);

        svg.select('.x-axis')
            .attr('transform', `translate(0,${110})`)
            .call(axisBottom(x));

        const brush = brushX()
            .extent([
                [10, 10],
                [810, 110],
            ])
            .on('start brush end', function () {
                const nodeSelection = brushSelection(
                    select(brushRef.current).node(),
                );
                const index = nodeSelection.map(x.invert);

                setPos(index);
            });

        console.log(pos);

        select(brushRef.current).call(brush).call(brush.move, [0, 100].map(x));
    }, [pos]);

    return (
        <svg ref={svgRef} width="1200" height={800}>
            <rect x={x(200)} y={10} width={400} height={100} fill={'blue'} />
            <g className="x-axis" />
            <g ref={brushRef} />
            <text>{pos[0]}-{pos[1]}</text>
        </svg>
    );
};

有什么想法可以解决这个问题吗?谢谢!

解答

似乎这可以解决问题:

const runBrushes = useCallback(async () => {
    const brush = brushX()
        .extent([
            [10, 10],
            [810, 110],
        ])
        .on('start brush end', function () {
            const nodeSelection = brushSelection(
                select(brushRef.current).node(),
            );
            const index = nodeSelection.map(x.invert);

            setPos(index);
        });

    select(brushRef.current).call(brush).call(brush.move, [0, 100].map(x));
}, [pos, x]);

useEffect(() => {
    const svg = select(svgRef.current);

    svg.select('.x-axis')
        .attr('transform', `translate(0,${110})`)
        .call(axisBottom(x));

    runBrushes().catch(console.error);
}, []);
Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐