将上下文传递给 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 并获取它的子上下文,使用 mountoptions 参数手动将其传递给 Beacon。这将测试 BeaconConfig 创建正确的子上下文并且 Beacon 正确使用上下文。当 Beacon 是后代时,它不会测试 BeaconConfig 将配置向下传递给 Beacon,但我们可以认为这是理所当然的,因为它是基本的 React 功能。