Свойство 'location' не существует для типа 'Readonly <{}> - React Router и Typescript - PullRequest
1 голос
/ 22 октября 2019

Я пытаюсь создать защищенный маршрут для аутентификации. У меня есть компонент ProtectedRoute, как предложено в документации, который выглядит следующим образом:

interface ProtectedRouteProps {
  auth: AuthState;
}

const ProtectedRoute = ({
  children,
  auth,
  ...rest
}: RouteProps & ProtectedRouteProps): JSX.Element => {
    console.log(auth)
  return (
    <Route
      {...rest}
      render={(props: RouteProps) =>
        auth.isAuthenticated ? children : <Redirect to={{pathname: "/signin", state: "Please sign in" }} />
      }
    />
  );
};

export default ProtectedRoute;

Затем я его использую и хочу показать состояние («пожалуйста, войдите в систему»), если кто-то перенаправлен настраница входа.

У меня есть компонент-обертка, который имеет дело с маршрутизацией:

export interface IWrapper {
    auth: AuthState
}

class Wrapper extends Component<IWrapper> {
    constructor(props: IWrapper){
        super(props);
        console.log(props)
    }
  render() {

    return (
      <div>
        <BrowserRouter>
          <HeaderContainer />
          <Switch>
          <Route exact path="/">
              <Home />
          </Route>
          <Route exact path="/signup">
            <SignUpView />
          </Route>
          <ProtectedRoute auth={this.props.auth} path="/dashboard">
              <DashboardContainer />
          </ProtectedRoute>
          </Switch>
          <Route exact path="/" component={Home}></Route>
          <Route exact path="/signout" component={SignUpView}></Route>
          <Route exact path="/signin" component={SignIn}></Route>

        </BrowserRouter>
      </div>
    );
  }
}

const mapStateToProps = (state: AppState) => ({
    auth: state.auth
})

export default connect(mapStateToProps)(Wrapper)

Вот моя страница входа:

export default class SignIn<RouteComponentProps> extends Component {
    constructor(props: RouteComponentProps){
        super(props);
        console.log(props);
    }


    render() {
        return (
            <div>
                {this.props.location.state ? (
                    <h2>You were redirected</h2>
                ) : ("")}
                <SignInForm />
            </div>
        )
    }
}

Компилятор машинописного текста говорит, что я не могу делать реквизиты.location, поскольку "Свойство location" не существует для типа "Readonly <{}> & Readonly <{children ?: ReactNode;}> '."

Я действительно не понимаю, что это значит. В определениях типов для RouteComponentProps у вас есть:

export interface RouteComponentProps<Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.LocationState> {
  history: H.History;
  location: H.Location<S>;
  match: match<Params>;
  staticContext?: C;
}

Так в чем же проблема? Я пробовал использовать реквизиты Redirect, но это тоже не работает. Я n00b в Typescript, поэтому, если кто-нибудь может помочь, я буду признателен. Спасибо.

1 Ответ

1 голос
/ 22 октября 2019

Не прочитав весь ваш код, я предполагаю, что вы можете просто изменить SignIn определение класса с

export default class SignIn<RouteComponentProps> extends Component { ... }

на

export default class SignIn extends Component<RouteComponentProps> { ... }

, тогда вам должно быть хорошоидти.

В общем универсальный тип параметры аннотируются после имени класса, которые в вашем случае не нужны. В предложении extends concrete установлены аргументы для расширяемого компонента. Если вы просто пишете extends Component и не указываете тип реквизита через Component<RouteComponentProps>, используется тип по умолчанию {} из Component, и TS не может найти свойство location в литерале общего объекта {}.

Больше информации об общих классах можно найти здесь .

...