TypeError:无法读取属性'scrollIntoView'的null - react。开胃酶

问题描述 投票:0回答:2

使用16.3.1是16.3.1,酶3.3.0。

在我的React Class组件中,我创建了一个react ref,我用它来确保在安装组件时浏览器位于页面顶部。

class PageView extends React.Component {

  constructor(props) {
    super(props);
    this.topOfPageRef = React.createRef();
  }

  componentDidMount() {
    ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
  }

  render(){
    const { x } = this.props;

    return (
      <React.Fragment>
        <div className="main-wrapper" ref={this.topOfPageRef}>
         Top
        </div>
        )}
      </React.Fragment>
    );
  }
}

这一切都在浏览器中完美运行,但在我的酶测试中失败了。

我的测试很简单,它只是尝试渲染组件。

  it('should render component correctly', () => {
    const props = {
      ...defaultProps,
    };
    const wrapper = mount(<PageView {...props} />);
    expect(wrapper).toMatchSnapshot();
  });

TypeError: Cannot read property 'scrollIntoView' of null

我已经尝试了shallow和mount方法,虽然找到的元素不是null,但它似乎是HTMLDivElement的反应实例,它缺少scrollIntoView方法。

javascript reactjs testing jestjs enzyme
2个回答
3
投票

错误消息说明

在上面的示例代码中使用mount会出现此错误:

TypeError: _reactDom2.default.findDOMNode(...).scrollIntoView is not a function

使用shallow会出现上面列出的错误:

TypeError: Cannot read property 'scrollIntoView' of null


问题

shallow不进行DOM渲染,因此永远不会有一个DOM节点可以调用scrollIntoView()

任何执行DOM操作的代码都需要使用mount提供的完整DOM渲染进行测试。


安装

"The default environment in Jest is a browser-like environment through jsdom"

"jsdom is a pure-JavaScript implementation of many web standards...[that] emulate[s] enough of a subset of a web browser to be useful for testing"

问题

jsdom实现了大部分浏览器环境,但它没有实现所有功能。特别值得注意的是,自scrollIntoView jsdom以来,它没有实施does not do layout and would therefore not be able to provide an accurate implementation

由于jsdom没有实现scrollIntoView,因此在jsdom提供的元素上将不会定义。

recommended approach from this Google dev是将以下行添加到测试代码中:

Element.prototype.scrollIntoView = () => {};

该行将添加scrollIntoView的noop实现到jsdom提供的Element

对于您的测试,您可以更进一步,并将scrollIntoView设置为spy以确保它被调用:

it('should render component correctly', () => {
  const props = {
    ...defaultProps,
  };
  Element.prototype.scrollIntoView = jest.fn();  // set scrollIntoView to a spy
  const wrapper = mount(<PageView {...props} />);
  expect(wrapper).toMatchSnapshot();
  expect(Element.prototype.scrollIntoView).toHaveBeenCalled();  // PASSES
});

此外,安东尼奥是正确的,你不应该使用ReactDOM.findDOMNode(),你应该能够直接使用this.topOfPageRef.current

componentDidMount() {
  this.topOfPageRef.current.scrollIntoView();
}

1
投票

您得到的错误是因为ReactDOM.findDOMNode返回null。

正如React doc所说:

当组件呈现为null或false时,findDOMNode返回null

在大多数情况下,您可以将引用附加到DOM节点,并完全避免使用findDOMNode。

您不应该使用React.findDOMNode

componentDidMount() {
   ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
}

但:

componentDidMount() {
   this.topOfPageRef.current.scrollIntoView();
}

希望它会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.