将上下文传递给 ReactJS 中动态添加的子项
Passing context to a dynamically added child in ReactJS
我正在尝试将上下文传递给 React 组件,但因为我正在使用 Enzyme 进行测试,所以我想将该组件动态添加到其父级,以便我可以检查其状态。测试看起来像这样:
describe('<BeaconConfig />', () => {
it('inherits the config from BeaconConfig', () => {
mount(<BeaconConfig persistent><div id="parent"></div></BeaconConfig>, { attachTo: document.body });
const wrapper = mount(<Beacon/>, { attachTo: document.getElementById('parent') });
expect(wrapper.state('persistent')).to.be(true);
});
});
测试失败,因为 Beacon
组件状态的 persistent
属性 是 undefined
,尽管它应该通过上下文从 BeaconConfig
继承。
当我尝试将 Beacon
直接放在 JSX 中时,当我挂载 BeaconConfig
时它工作正常,但在这种情况下 Enzyme 不会让我进入 Beacon
组件状态,因为它不是根。
当我将它动态添加到其父组件时,React 不将上下文传播到我的组件是否正常?
React 不传播上下文是正常的 - 它不会查看 DOM 并以这种方式将其与 VDOM 进行区分。
您需要在初始挂载中将其设为 child,并使用 MountWrapper (docs) 的 .find()
或 .children()
方法进行挖掘children,找到信标并做你的断言。
这是我最终使用的完整测试:
describe('Context', () => {
let wrapper;
let parent;
const open = stub().returns({});
const mockIndexedDB = { open };
const config = mount(<BeaconConfig persistent position="bottom" indexedDB={mockIndexedDB} />);
beforeEach(() => {
parent = document.createElement('div');
document.body.appendChild(parent);
wrapper = mount(<Beacon>some text</Beacon>, {
attachTo: parent,
context: config.instance().getChildContext()
});
});
afterEach(() => {
wrapper.detach();
document.body.removeChild(document.body.firstChild);
});
it('overrides the default values with the context if any', () => {
expect(wrapper.state('persistent')).to.be(true);
expect(wrapper.state('position')).to.be('bottom');
expect(open.calledOnce).to.equal(true);
});
});
@STRML 有一个很好的建议,但我认为不可能访问非根组件的状态。
相反,我单独实例化 BeaconConfig
并获取它的子上下文,使用 mount
的 options
参数手动将其传递给 Beacon
。这将测试 BeaconConfig
创建正确的子上下文并且 Beacon
正确使用上下文。当 Beacon
是后代时,它不会测试 BeaconConfig
将配置向下传递给 Beacon
,但我们可以认为这是理所当然的,因为它是基本的 React 功能。
我正在尝试将上下文传递给 React 组件,但因为我正在使用 Enzyme 进行测试,所以我想将该组件动态添加到其父级,以便我可以检查其状态。测试看起来像这样:
describe('<BeaconConfig />', () => {
it('inherits the config from BeaconConfig', () => {
mount(<BeaconConfig persistent><div id="parent"></div></BeaconConfig>, { attachTo: document.body });
const wrapper = mount(<Beacon/>, { attachTo: document.getElementById('parent') });
expect(wrapper.state('persistent')).to.be(true);
});
});
测试失败,因为 Beacon
组件状态的 persistent
属性 是 undefined
,尽管它应该通过上下文从 BeaconConfig
继承。
当我尝试将 Beacon
直接放在 JSX 中时,当我挂载 BeaconConfig
时它工作正常,但在这种情况下 Enzyme 不会让我进入 Beacon
组件状态,因为它不是根。
当我将它动态添加到其父组件时,React 不将上下文传播到我的组件是否正常?
React 不传播上下文是正常的 - 它不会查看 DOM 并以这种方式将其与 VDOM 进行区分。
您需要在初始挂载中将其设为 child,并使用 MountWrapper (docs) 的 .find()
或 .children()
方法进行挖掘children,找到信标并做你的断言。
这是我最终使用的完整测试:
describe('Context', () => {
let wrapper;
let parent;
const open = stub().returns({});
const mockIndexedDB = { open };
const config = mount(<BeaconConfig persistent position="bottom" indexedDB={mockIndexedDB} />);
beforeEach(() => {
parent = document.createElement('div');
document.body.appendChild(parent);
wrapper = mount(<Beacon>some text</Beacon>, {
attachTo: parent,
context: config.instance().getChildContext()
});
});
afterEach(() => {
wrapper.detach();
document.body.removeChild(document.body.firstChild);
});
it('overrides the default values with the context if any', () => {
expect(wrapper.state('persistent')).to.be(true);
expect(wrapper.state('position')).to.be('bottom');
expect(open.calledOnce).to.equal(true);
});
});
@STRML 有一个很好的建议,但我认为不可能访问非根组件的状态。
相反,我单独实例化 BeaconConfig
并获取它的子上下文,使用 mount
的 options
参数手动将其传递给 Beacon
。这将测试 BeaconConfig
创建正确的子上下文并且 Beacon
正确使用上下文。当 Beacon
是后代时,它不会测试 BeaconConfig
将配置向下传递给 Beacon
,但我们可以认为这是理所当然的,因为它是基本的 React 功能。