reactjs - Typen '{}' saknar följande egenskaper från typen


I mitt React-projekt får jag följande fel för min App-komponent.

Type '{}' is missing the following properties from type 'Pick<ClassAttributes<App> & RouteChildrenProps<{}, unknown> & { userData: UserDataType | undefined; userRightList: UserRightListType[] | undefined; userPermissionList: string[] | undefined; } & { ...; }, "ref" | ... 3 more ... | "key">': history, location, matchts(2739)

Följande är min index.tsx-filkod:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import App from './App';
import reportWebVitals from './reportWebVitals';
import reduxStore from './redux/store';

ReactDOM.render(
  <Provider store={reduxStore.store}>
    <BrowserRouter>
      <App /> // getting the error here
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);

reportWebVitals();

och följande är min App.tsx-filkod:

import { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router-dom';
import ErrorBoundary from './components/ErrorBoundary';
import { getUserByToken, getUserRights, setUserRights } from './redux/actions';
import { ReduxStateType } from './type-definitions';
import { isAuthenticated } from './utils/is-authenticated';

type StoreProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatch;

type PropsType = RouteComponentProps & StoreProps & DispatchProps;

class App extends Component<PropsType, any> {
  componentDidMount() {
    const {
      userData,
      getUserByToken,
      getUserRights,
      userRightList,
    } = this.props;
    const isAuth = isAuthenticated(userData);
    if (!userData?.username && isAuth) {
      getUserByToken();
    }
    if (userRightList?.length === 0 && isAuth) {
      getUserRights();
    }
  }

  componentDidUpdate(prevProps: PropsType) {
    const {
      userData,
      userRightList,
      userPermissionList,
      setUserRights,
    } = this.props;

    if (
      userData &&
      Object.keys(userData).length > 0 &&
      userRightList &&
      userRightList?.length > 0 &&
      userPermissionList?.length === 0
    ) {
      setUserRights();
    }
  }

  render() {
    return (
      <Fragment>
        <ErrorBoundary></ErrorBoundary>
      </Fragment>
    );
  }
}

function mapStateToProps(state: ReduxStateType) {
  return {
    userData: state.auth?.userData,
    userRightList: state.auth?.userRightList,
    userPermissionList: state.shared?.userPermissionList,
  };
}

const mapDispatch = {
  getUserByToken,
  getUserRights,
  setUserRights,
};

export default connect<StoreProps, DispatchProps>(
  mapStateToProps,
  mapDispatch
)(App);

Jag får ett fel i filen index.tsx i render-metoden. Jag är ny på TypeScript. Jag skulle uppskatta det mycket om någon kan berätta för mig var jag gör fel.

Svar #1

Du har två olika paket som kan injicera sina egna props i din komponent: Redux och React Router.

När du definierar din komponent som class App extends Component<PropsType, any>, förväntar den sig att få PropsType som sina props.

type PropsType = RouteComponentProps & StoreProps & DispatchProps;

Det behöver ta emot alla tre av de gränssnitt som du har listat som props. StoreProps och DispatchProps är de som injiceras av Redux connect-högre ordningens komponent, och dessa är okej. Ditt felmeddelande säger att de saknade props är history, location och match. Dessa är egenskaperna hos RouteComponentProps.

Just nu använder din komponent faktiskt inte några av Router-egenskaperna, så den enklaste lösningen är helt enkelt att ta bort RouteComponentProps från PropsType. Genom att ha det där kräver du att dessa egenskaper ska vara närvarande.

Om du faktiskt vill inkludera RouteComponentProps, måste ändringar göras i index.tsx. Du har omslutit din App i en BrowserRouter, men det gör egentligen ingenting eftersom du inte har definierat några rutter. Du behöver en Switch-komponent med Route-komponenter inuti den. Om App laddas inom en Route-komponent, kommer RouteComponentProps att injiceras.

Kolla in React Router-dokumentationen för hur man ställer in flera rutter. Detta kommer alltid att ladda App (så ingen förändring), men nu kommer det att få de nödvändiga props. Det finns flera sätt att deklarera komponenten för en Route, men du vill använda component-propen eller render-propen istället för children eftersom dessa låter TypeScript veta att router-props ingår.

ReactDOM.render(
  <Provider store={reduxStore.store}>
    <BrowserRouter>
      <Switch>
        <Route
          path="/"
          component={App}
        />
      </Switch>
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);