错误参考:不定定义React |在角度使用反应组件
2021-03-09
1648
所以基本上我想将一个单一的 React 组件(通知组件)渲染到我的 Angular 项目中。我创建了
Notification.tsx
import * as React from 'react';
import { FunctionComponent, useEffect, useRef, useState } from 'react';
import { IconButton, Badge, Menu, List, ListItem, ListItemIcon, ListItemText, ListItemSecondaryAction, Avatar } from '@material-ui/core';
import { Notifications, Delete, Event, HourglassEmpty, Alarm } from '@material-ui/icons';
import { makeStyles } from '@material-ui/core/styles';
import { grey } from '@material-ui/core/colors';
export interface NotificationProps { }
export const NotificationComponent: FunctionComponent<NotificationProps> = (props: NotificationProps) => {
return <div className={"row"}>
<IconButton disableRipple={true} aria-label="notification" className="py-3 my-auto"
onClick={handleNotificationMenuClick} aria-controls="notification-drop-down-menu"
aria-haspopup="true">
<Badge badgeContent={4} max={99} color="secondary">
<Notifications />
</Badge>
</IconButton>
</div>
};
一个包装器组件
NotificationWrapper.tsx
import { AfterViewInit, Component, ElementRef, OnChanges, OnDestroy, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
import { NotificationComponent } from './Notification';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'notificationComponentTemplate';
@Component({
selector: 'react-notification-component',
template: `<span #${containerElementName}></span>`,
encapsulation: ViewEncapsulation.None,
})
export class NotificationWrapper implements OnChanges, OnDestroy, AfterViewInit {
@ViewChild(containerElementName, { static: false }) containerRef: ElementRef;
constructor() { }
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
ReactDOM.render(<div className={'notification-wrapper'}>
<NotificationComponent />
</div>, this.containerRef.nativeElement);
}
}
将此包装器添加到
app.module.ts
的
@NgModule
import { NotificationWrapper } from "../react-components/notification/NotificationWrapper";
@NgModule({
declarations: [
NotificationWrapper,
],
})
使用通知包装器选择器如下:
<div class="col-sm-6">
<react-notification-component></react-notification-component>
</div>
在本地提供服务时一切正常,正如我在此网站上遇到的其他类似问题一样:我已将
“jsx”:“react”
添加到
tsconfig.json
、
plugins: [
new webpack.ProvidePlugin({
"React": "react",
})
]
和
externals: {
'react': 'React'
},
到
webpack.config.js
。以下是整个文件,供您参考。
// Work around for https://github.com/angular/angular-cli/issues/7200
const path = require('path');
const webpack = require('webpack');
// change the regex to include the packages you want to exclude
const regex = /firebase\/(app|firestore)/;
module.exports = {
mode: 'production',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts'
},
externals: {
'./dist/server/main': 'require("./server/main")',
'react': 'React'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
resolve: { extensions: ['.ts', '.js'] },
target: 'node',
mode: 'none',
// this makes sure we include node_modules and other 3rd party libraries
externals: [/node_modules/, function (context, request, callback) {
// exclude firebase products from being bundled, so they will be loaded using require() at runtime.
if (regex.test(request)) {
return callback(null, 'commonjs ' + request);
}
callback();
}],
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
noParse: /polyfills-.*\.js/,
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `@angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true },
},
]
},
plugins: [
new webpack.ProvidePlugin({
"React": "react",
}),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};
我的问题是,当我构建应用程序时,通知组件未呈现,控制台中出现此错误
ERROR ReferenceError: React is not defined
。我是否遗漏了什么?提前致谢。
2个回答
我认为这是一个典型的不必要的优化,在最终的 js 中删除 React(React 不直接使用)
尝试调用 React 上的方法或属性,如 React.version :
import {
OnChanges,
ViewChild
} from '@angular/core';
import { MyComponent } from './react/MyComponent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'myReactComponentContainer';
@Component({
...
})
export class MyComponent implements OnChanges {
@ViewChild(containerElementName) containerRef: ElementRef;
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
private render() {
React.version;
ReactDOM.render(<MyReactComponent />, this.containerRef.nativeElement);
}
}
hmarchadour
2021-07-02
将以下内容添加到
tsconfig.json
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react",
}
在
angular.json
中将
aot
和
buildOptimizer
设置为 false
将
import * as React from 'react';
import * as ReactDOM from 'react-dom'
替换为
import React from 'react';
import ReactDOM from 'react-dom';
Durk
2021-03-10