reactjs 某些组件“不能用作JSX组件”

xtfmy6hx  于 2023-01-12  发布在  React
关注(0)|答案(5)|浏览(641)

问题总结:

在这个周末没有修改代码的情况下,一些类组件开始给我以下错误。

'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 inpm 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"
  ]
}
imzjd6km

imzjd6km1#

我更新了reactreact-dom

npm i react@18 react-dom@18 @types/react@18 @types/react-dom@18
qybjjes1

qybjjes12#

对于react-native expo空白 typescript 模板,我必须添加
package.json

"resolutions": {
    "@types/react": "~17.0.47"
  },

然后再次执行yarn install
tsconfig.json

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "esModuleInterop": true,
    "strict": true,
    "jsx": "react"
  }
}
xwbd5t1u

xwbd5t1u3#

React 18已发布,但似乎损坏了多个将其@types/react依赖性设置为*的软件包:https://github.com/facebook/react/issues/24304

xpszyzbs

xpszyzbs4#

我在React Native Typescript项目中通过更改导入React的方式修复了这个问题。我将import语句更改为:
import * as React from 'react';
而且奏效了!

toe95027

toe950275#

这个问题可能是通过其他一些包的对等依赖关系引入到您的项目中的。
如果您有.tsconfig文件,请将以下内容添加到compilerOptions:

"paths": {
"react": [ "./node_modules/@types/react" ]
}

相关问题