Javascript 茉莉花试验中反应组分状态的更新
我有一个相对简单的React组件,它根据列表的状态呈现列表。然后我有一个karma/jasmine测试来呈现组件,设置其状态,并检查是否呈现了正确的标记 我遇到的问题是,每当我在我的组件上执行Javascript 茉莉花试验中反应组分状态的更新,javascript,reactjs,Javascript,Reactjs,我有一个相对简单的React组件,它根据列表的状态呈现列表。然后我有一个karma/jasmine测试来呈现组件,设置其状态,并检查是否呈现了正确的标记 我遇到的问题是,每当我在我的组件上执行setState({})或forceUpdate()时,我都会收到一个错误: TypeError: 'undefined' is not an object (evaluating 'deepestAncestor.firstChild') at /home/company/projects
setState({})
或forceUpdate()
时,我都会收到一个错误:
TypeError: 'undefined' is not an object (evaluating 'deepestAncestor.firstChild')
at /home/company/projects/user_interface_kit/bower_components/react/react.js:10314
测试React组件中状态变化的正确方法是什么
反应代码:
编辑:完整堆栈跟踪
这里有一个小项目再现了这个问题
深入了解React和React\u with\u插件的工作原理后,测试中的本地React对象似乎与React\u with\u插件使用的React实例不同。因此,如果您在测试中这样做:
react_with_addons.addons.TestUtils.renderIntoDocument(componentInstance);
然后react_with_addon的react实例注册componentInstance并初始化其nodeCache对象。本地React实例保持不变。然后,如果您尝试像这样更新组件的状态:
componentInstance.updateState({key:'newValue'});
React的本地实例用于尝试更新DOM。由于此实例从未装入任何组件,因此更新失败,并且您会得到“未定义”不是对象(评估“deepestAncestor.firstChild”)错误
有趣的是,如果您将任何组件装入本地React,那么在更新组件的状态时将不会看到错误,即使该组件是使用React\u with\u addon的React对象装入的
如果您的测试需要运行setState,那么现在避免这个问题的最好方法就是不要使用react_with_插件的renderIntoDocument函数。相反,只需创建自己的。它只有两行:
function renderIntoDocument(instance) {
var div = document.createElement('div');
return React.renderComponent(instance, div);
};
我不知道前面的答案是否仍然正确 对于React 0.11.1,此代码可以正常工作:
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
jest.dontMock('public/components/MyThing.jsx');
var MyThing = require('public/components/MyThing.jsx');
describe('MyThing', function() {
var html;
describe('#render', function() {
beforeEach(function(){
var component = MyThing();
var componentInstance = TestUtils.renderIntoDocument(component);
componentInstance.setState({isCool: true});
html = componentInstance.getDOMNode().textContent;
});
it('includes something cool', function(){
expect(html).toContain('something cool');
});
});
});
您仍然可以使用原始的TestUtils.renderIntoDocument,只需要将React移到beforeach。因为如果需要全局响应,每个测试的上下文都会不同,这会导致两个不同的实例装载相同的组件
beforeEach(function () {
React = require('react/addons');
TestUtils = React.addons.TestUtils;
});
这是RenderToDocument源代码(我在项目中使用的React 0.14.8): 这是两年前改变的时间: 因此,尽管名称不同,它实际上并不会将任何内容呈现到文档中 我还可以确认,Assaf的答案仍然适用于0.14.8-基本上,编写自己的RenderToDocument。以下是对我有效的方法:
函数renderIntoDocument(实例){
var div=document.createElement('div');
document.documentElement.appendChild(div);
返回ReactDOM.render(实例,div);
}
您可以发布更多的堆栈跟踪吗?您的测试的哪一行导致抛出异常?一个最小的重新编译用例(在jsbin等中)会很有帮助;你不应该犯那样的错误。请随意在react-repo上作为bug进行归档。我添加了完整的堆栈跟踪。导致异常的行是.setState()。如果手动更新state对象并在forceUpdate调用中调用forceUpdate(),则会出现相同的错误。当组件试图重新呈现自身时,似乎会发生此错误。@BenAlpert我无法轻松制作jsbin/fiddle,但我创建了一个小项目来重现此问题。非常简单,任何人都可以验证这是否仍然适用于0.12.*
?这仍然是有效的黑客攻击吗?或者现在有一个好的解决方法吗?我猜这不再有效,因为React自编写此答案以来经历了许多更改。在调试了近一周后,此答案救了我:)有趣的是,它可能不会使他们的测试失败,但肯定会让我的测试失败(因为我的代码期望element.ownerDocument.body.contains(element)
为所有呈现的元素返回true)。
function renderIntoDocument(instance) {
var div = document.createElement('div');
return React.renderComponent(instance, div);
};
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
jest.dontMock('public/components/MyThing.jsx');
var MyThing = require('public/components/MyThing.jsx');
describe('MyThing', function() {
var html;
describe('#render', function() {
beforeEach(function(){
var component = MyThing();
var componentInstance = TestUtils.renderIntoDocument(component);
componentInstance.setState({isCool: true});
html = componentInstance.getDOMNode().textContent;
});
it('includes something cool', function(){
expect(html).toContain('something cool');
});
});
});
beforeEach(function () {
React = require('react/addons');
TestUtils = React.addons.TestUtils;
});