我正在测试我创建的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
失败了。
1条答案
按热度按时间2g32fytz1#
https://reactjs.org/docs/test-renderer.html#ideas 建议这样做,但我遇到了完全相同的问题。
您可以尝试
awaitFor
示例来完成渲染,因为refs
在渲染阶段之后才设置。我不确定它是否有效。也许最好将问题提交到React页面。