d3.js 我如何测试我的'useRef'实现?

uqzxnwby  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(164)

我正在测试我创建的React组件,其中大部分渲染都委托给了使用useEffect的D3。为了使useEffect正常工作,我需要访问由React在useRef中添加的DOM元素。

const Axis = ({
    ...
}) => {
    ...
    const scale = useSelector((s) => chartSelectors.scales.getScale(s, field));

    // React will own the axis containers, but D3 will own the axis themselves
    const axis = useRef(null);

    // Render the x-axis using D3
    useEffect(() => {
        console.log(axis.current);

        if (axis.current && scale) {
            const selection = d3
                .select(axis.current)
                .transition()
                .duration(animationDuration);

            // Create the D3 axis renderer
            const d3Axis = getD3Axis(position);

            // Set some scale props
            d3Axis
                .scale(scale)
                .tickSizeInner(tickSizeInner)
                .tickSizeOuter(tickSizeOuter)
                .tickPadding(tickPadding);

            // Render the axis
            selection.call(d3Axis);
        }
    }, [
        axis,
        scale,
    ]);

    return (
        <React.Fragment>
            <Title position={position} title={title} fields={fields} />
            <g transform={transform}>
                {showGridlines ? <Gridlines position={position} scale={scale} /> : null}
                <g className="axis" ref={axis} />
            </g>
        </React.Fragment>
    );
};

上面的关键部分是axis ref,它应该由React设置,然后useEffect显然需要访问axis.current。然而,当我的测试运行时,它总是null。如果我在测试中添加一个人工等待,它将第二次渲染,也是使用null的值。
示例测试:

it('renders a left axis', async () => {
            const layer = { current: document.createElement('custom') };

            TestRenderer.act(() => {
                TestRenderer.create(
                    <Provider store={store}>
                        <Axis
                            layer={layer}
                            position="left"
                            fields={['y']}
                            showGridlines={false}
                        />
                    </Provider>,
                ).toJSON();
            });

            await new Promise((resolve) => {
                setTimeout(resolve, 500);
            });

            expect(layer.current).toMatchSnapshot();
        });

我的问题是,如何让useRef在这个测试中正常工作?我试过模拟useRef,但是由于应用的其他部分(在这个例子中是Redux提供程序)在内部使用useRef,这会以其他可怕的方式中断,因为useSelectors失败了。

2g32fytz

2g32fytz1#

https://reactjs.org/docs/test-renderer.html#ideas 建议这样做,但我遇到了完全相同的问题。
您可以尝试awaitFor示例来完成渲染,因为refs在渲染阶段之后才设置。我不确定它是否有效。也许最好将问题提交到React页面。

相关问题