问题总结:
在这个周末没有修改代码的情况下,一些类组件开始给我以下错误。
'EverySelector' cannot be used as a JSX component.
Its element type 'ReactElement<any, any> | Component<Omit<EverySelectorProps, keyof WithTranslation>, any, any> | null' is not a valid JSX element.
Type 'Component<Omit<EverySelectorProps, keyof WithTranslation>, any, any>' is not assignable to type 'Element | ElementClass | null'.
Type 'Component<Omit<EverySelectorProps, keyof WithTranslation>, any, any>' is not assignable to type 'ElementClass'.
The types returned by 'render()' are incompatible between these types.
Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react-transition-group/node_modules/@types/react/index").ReactNode'.ts(2786)
并不是每个类组件都是这样,我将在Show Some Code
部分给出例子。
当我要求我的同事在他的一个旧分支上执行npm i
和npm run build
时,它通过了,他没有任何错误。当我 checkout 他的分支并执行同样的操作时,它仍然给我同样的错误。我已经清理了我的缓存,并在他的分支上执行了干净安装。
我的尝试
1.我认为我的一个包正在破坏我,所以我从package.json中删除了所有^
:"redux": "^4.0.5"
到"redux": "4.0.5"
。但是问题仍然存在。
1.基于Type 'React.ReactNode' is not assignable to type 'import(".../node_modules/@types/react-transition-group/node_modules/@types/react/index").ReactNode'.ts(2786)
,我开始尝试@types/react
和@types/react-dom
的版本。
1.玩过导出。我注意到的第一个组件是<Header/>
,它有以下导出
export default withRouter(
connect(mapStateToProps, actions)(withStyles(styles)(withTranslation()(Header)))
);
我改成了
export default connect(mapStateToProps, actions)(withStyles(styles)(withTranslation()(Header)));
这使得<Header/>
停止抛出错误,但我注意到许多其他类似的错误与withRouter
无关,这使我相信这个问题与react-router-dom
无关。后来,我收到的错误是在index.tsx
:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
显示部分代码
这是一个损坏的组件EverySelector
:
//EverySelector.tsx
import React, { ChangeEvent, Component, ReactNode } from 'react';
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';
import { WithTranslation, withTranslation } from 'react-i18next';
class EverySelector extends Component<EverySelectorProps> {
private handleOnEveryChange = (event: SelectChangeEvent<number>, child: ReactNode): void => {
event.target.value && this.props.onEveryChanged(event.target.value as number);
};
private generateDropdownOptions = (): number[] => {
let options = [1, 2, 3, 5, 10, 15, 30, 60];
const roundHoursToBeIncluded = [1, 2, 4, 8, 12, 24, 48];
roundHoursToBeIncluded.map((roundHour: number) => {
if ((roundHour * 60) % this.props.confEvery === 0) {
const roundHourOption = (roundHour * 60) / this.props.confEvery;
if (!options.includes(roundHourOption)) {
options.push(roundHourOption);
}
}
});
return options.sort((a: number, b: number) => a - b);
};
private convertMinutesToString = (totalMinutes: number): string => {
const days = Math.floor(totalMinutes / 1440); // 60 * 24
const hours = Math.floor((totalMinutes - days * 1440) / 60);
const minutes = Math.round(totalMinutes % 60);
let output = '';
if (days > 0) {
output += days + ' ' + `${days === 1 ? this.props.t('day') : this.props.t('days')}`;
}
if (hours > 0) {
output += `${days > 0 ? ' ' : ''}${hours} ${
hours === 1 ? this.props.t('hour') : this.props.t('hours')
}`;
}
if (minutes > 0) {
output += `${days > 0 || hours > 0 ? ' ' : ''}${minutes} ${
minutes === 1 ? this.props.t('minute') : this.props.t('minutes')
}`;
}
return output;
};
public render(): React.ReactNode {
return (
<FormControl variant="outlined" size="small">
<InputLabel>Every</InputLabel>
<Select
id="every_selector"
value={this.props.every}
onChange={this.handleOnEveryChange}
fullWidth
autoWidth
label="Every"
>
{this.generateDropdownOptions().map((i: number) => (
<MenuItem value={i}>{this.convertMinutesToString(this.props.confEvery * i)}</MenuItem>
))}
</Select>
</FormControl>
);
}
}
interface EverySelectorProps extends WithTranslation {
confEvery: number;
every: number;
onEveryChanged: (every: number) => void;
}
export default withTranslation()(EverySelector);
这是一个工作组件DateSelectorAverage
:
//DateSelectorAverage.tsx
import { Grid, TextField } from '@mui/material';
import moment from 'moment';
import React, { ChangeEvent, Component } from 'react';
import { connect } from 'react-redux';
import {
AvgFromDatePeriodAction,
AvgToDatePeriodAction,
} from '../../../state_management/actions/PeriodSelectionAction';
import { PeriodSelectionActionCreator } from '../../../state_management/actions/PeriodSelectionActionCreator';
class DateSelectorAvg extends Component<DateSelectorAvgProps> {
public render(): React.ReactNode {
return (
<Grid container spacing={3} direction="row">
<Grid item>
<TextField
label="Average From Date"
type="date"
size="small"
variant="outlined"
value={moment(this.props.avgFromDate).format('YYYY-MM-DD')}
onChange={(event: ChangeEvent<HTMLInputElement>): void => {
this.props.periodAvgFromDateChanged(new Date(event.target.value));
}}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item>
<TextField
label="Average To Date"
type="date"
size="small"
variant="outlined"
value={moment(this.props.avgToDate).format('YYYY-MM-DD')}
onChange={(event: ChangeEvent<HTMLInputElement>): void => {
this.props.periodAvgToDateChanged(new Date(event.target.value));
}}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
</Grid>
);
}
}
interface DateSelectorAvgProps extends DateSelectorAvgOwnProps, StateProps, DispatchProps {}
interface DateSelectorAvgOwnProps {}
interface StateProps {
avgFromDate: Date;
avgToDate: Date;
}
interface DispatchProps {
periodAvgFromDateChanged: (date: Date | null) => AvgFromDatePeriodAction;
periodAvgToDateChanged: (date: Date | null) => AvgToDatePeriodAction;
}
const mapStateToProps = (stateProps: { period: StateProps }): StateProps => ({
avgFromDate: stateProps.period.avgFromDate,
avgToDate: stateProps.period.avgToDate,
});
const mapDispatchToProps: DispatchProps = {
periodAvgFromDateChanged: PeriodSelectionActionCreator.changeAvgFromDate,
periodAvgToDateChanged: PeriodSelectionActionCreator.changeAvgToDate,
};
export default connect(mapStateToProps, mapDispatchToProps)(DateSelectorAvg);
package.json
{
"name": "device-counter-collector-gui",
"version": "0.1.1-SNAPSHOT",
"private": true,
"devDependencies": {
"@types/chart.js": "2.9.32",
"@types/googlemaps": "3.30.16",
"@types/jest": "26.0.19",
"@types/lodash": "4.14.171",
"@types/markerclustererplus": "2.1.33",
"@types/node": "14.14.16",
"@types/react": "17.0.39",
"@types/react-dom": "17.0.11",
"@types/react-redux": "7.1.14",
"@types/react-router-dom": "5.1.6",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"eslint-config-prettier": "7.1.0",
"eslint-plugin-prettier": "3.3.0",
"eslint-plugin-react": "7.21.5",
"prettier": "2.2.1",
"react-router-prop-types": "1.0.5",
"redux-devtools-extension": "2.13.5"
},
"dependencies": {
"@date-io/date-fns": "1.3.13",
"@emotion/react": "11.7.1",
"@emotion/styled": "11.6.0",
"@mui/icons-material": "5.4.2",
"@mui/lab": "5.0.0-alpha.69",
"@mui/material": "5.4.2",
"@mui/styles": "5.4.2",
"acorn-jsx": "5.0.0",
"axios": "0.14.0",
"chart.js": "2.9.4",
"chartjs-plugin-zoom": "0.7.7",
"colorbrewer": "1.0.0",
"date-fns": "2.28.0",
"dotenv-cli": "4.1.0",
"eslint": "7.17.0",
"formik": "2.2.9",
"i18next": "21.6.12",
"i18next-browser-languagedetector": "3.0.1",
"jwt-decode": "2.2.0",
"lodash": "4.17.21",
"material-ui-popup-state": "1.0.1",
"moment": "2.18.1",
"moment-timezone": "0.5.33",
"node-polyfill-webpack-plugin": "1.1.4",
"path-browserify": "1.0.1",
"path-to-regexp": "1.7.0",
"pondjs": "0.8.5",
"react": "17.0.2",
"react-autobind": "1.0.6",
"react-bootstrap": "0.32.4",
"react-bootstrap-table": "4.3.1",
"react-chartjs-2": "2.11.1",
"react-device-detect": "2.0.1",
"react-dom": "16.8.6",
"react-easy-chart": "1.0.0",
"react-file-download": "0.3.3",
"react-flexbox-grid": "1.0.2",
"react-ga": "3.3.0",
"react-google-maps": "9.4.5",
"react-google-maps-loader": "4.2.3",
"react-i18next": "11.15.5",
"react-icons": "4.3.1",
"react-jss": "8.6.1",
"react-recaptcha-google": "1.1.1",
"react-redux": "7.1",
"react-router-dom": "5.3.0",
"react-scripts": "5.0.0",
"react-select": "1.0.0-rc.2",
"react-timeseries-charts": "0.15.5",
"redux": "4.0.5",
"redux-thunk": "2.2.0",
"typescript": "4.5.2",
"uuid": "2.0.3",
"webpack": "4.44.2"
},
"scripts": {
"start": "react-scripts start",
"lint": "eslint . --ext .js --ext .ts --ext .tsx",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:8080",
"homepage": "./",
"module": {
"noParse": "./~/object-hash/dist/object_hash.js"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
5条答案
按热度按时间imzjd6km1#
我更新了
react
和react-dom
。qybjjes12#
对于react-native expo空白 typescript 模板,我必须添加
package.json
然后再次执行
yarn install
tsconfig.json
xwbd5t1u3#
React 18已发布,但似乎损坏了多个将其
@types/react
依赖性设置为*
的软件包:https://github.com/facebook/react/issues/24304xpszyzbs4#
我在React Native Typescript项目中通过更改导入React的方式修复了这个问题。我将import语句更改为:
import * as React from 'react';
而且奏效了!
toe950275#
这个问题可能是通过其他一些包的对等依赖关系引入到您的项目中的。
如果您有.tsconfig文件,请将以下内容添加到compilerOptions: