我正在使用Angular 2+创建网站,但我还想使用某些React组件的库。那不应该那么难;但是,问题是这些组件需要react-redux Provider在根级别使用Redux存储才能工作。基本上文档树应该如下所示:
<body>
...
<Provider store={store}>
<span>
<app-contents></app-contents>
<TopLevelComponent/>
</span>
</Provider>
...
</body>
...其中<app-contents>
是一个包含大部分网站内容的Angular组件,其中包含各种React组件的用法;和TopLevelComponent是另一个。
首先,我尝试使用@ngui/react来呈现React组件。这似乎可以用于小组件,虽然他们(正确地)抱怨无法访问商店。但是当用于提供者时,如下所示:
@Component({
selector: 'app-provider',
template: `
<ngui-react [reactComponent]="provider" [reactProps]="{store: theStore}">
<span>
<app-provider-contents></app-provider-contents>
<ngui-react [reactComponent]="topLevelComponent"></ngui-react>
</span>
</ngui-react>`
})
export class ProviderComponent {
provider = Provider;
topLevelComponent = TopLevelComponent;
constructor(@Inject(TheStore) public theStore: Redux.Store<any>) {}
}
......导致错误:
Warning: Failed prop type: Invalid prop `children` of type `array` supplied to `Provider`, expected a single ReactElement.
in Provider
和
ERROR Error: React.Children.only expected to receive a single React element child.
在我看来,原因可能是@ ngui / react过时了,所以我尝试在代码中动态创建Provider:
constructor(@Inject(TheStore) private theStore: Redux.Store<any>,
private elementRef: ElementRef) {}
ngAfterViewInit() {
const contents = React.createElement('app-contents', {key: this.randomKey}, null);
const provider = React.createElement(Provider, {store: this.theStore, key: this.randomKey}, contents);
ReactDOM.render(provider, this.elementRef.nativeElement, () => {});
}
get randomKey() { /* returns a pseudorandom string */ }
这导致:
<app-provider _ngcontent-c0="" _nghost-c1="">
<app-contents></app-contents>
</app-provider>
...但<app-contents>
未作为Angular组件加载,并且保持为空。
最后,我尝试使用这种情况并动态加载Angular组件。似乎有很多解决方案,但许多要求父元素通过各种指令,@ ViewChild和诸如此类的静态存在。然后,当我找到可以在给定DOM元素下插入的解决方案时:
const factory = this.factoryResolver.resolveComponentFactory(ProviderContentComponent);
const node = this.viewContainerRef.element.nativeElement.lastChild;
const component = factory.create(this.viewContainerRef.parentInjector, [], node);
this.viewContainerRef.insert(component.hostView);
...它呈现组件,但它将节点弹出到更高级别,并且其中的React组件再次抱怨无法访问商店:
<app-provider _ngcontent-c0="" _nghost-c1=""></app-provider>
<app-content _nghost-c2="" ng-version="4.4.4">
content works!
<!-- react component missing the store -->
</app-content>
所以,现在我想知道,实际上是否可以从Angular上下文,React Provider,Angular上下文切换到React组件,以便它可以工作?或者我是否必须摆脱React库并在Angular中本地生成组件?