Как установить состояние в компоненте React с помощью React-Router и RouteComponentProps (TypeScript)? - PullRequest
0 голосов
/ 30 января 2020

Я учусь на React и React-Router и хочу создать очень маленькую страницу входа, где пользователь может войти на секретную страницу. Я использую TypeScript.

Я сделал пример работы здесь: https://codesandbox.io/s/tender-mirzakhani-j1sdc?fontsize=14&hidenavigation=1&theme=dark

Я не уверен, что я объявил PropsType правильный, чтобы применить его на компоненте Login. И при использовании RouteComponentProps в качестве свойств у меня, кажется, нет доступа к состоянию компонента, поэтому я могу установить isAuthenticated=true.

Так что мой вопрос в том, как я могу обновить состояние, чтобы isAuthenticated получал новое значение истины? Поскольку this.state.isAuthenticated недоступен из компонента Вход в систему, но this.props.isAuthenticated - это!

Нужно ли мне сопоставлять состояние с реквизитами, чтобы получить обновленное состояние, или что именно мне нужно, чтобы получить это, когда я Хотите?

Подводя итог кода, который я имею в приведенном выше примере:

index.tsx:

import * as React from "react";
import { render } from "react-dom";
import { Layout } from "./App";

const rootElement = document.getElementById("root");
render(<Layout />, rootElement);

App.tsx

import * as React from "react";
import { Component } from "react";
import { Login } from "./loginpage";
import { SecretPage } from "./secretpage";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Redirect
} from "react-router-dom";
import "./styles.css";

export class Layout extends Component<{}, {}> {
  public render() {
    return (
      <Router>
        <Switch>
          <Route path="/login">
            <Login
              history={null}
              location={null}
              match={null}
              isAuthenticated={false}
            />
          </Route>
          <Route path="/">
            <Redirect to="/login" />;
          </Route>
          <Route path="/secret">
            <SecretPage />
          </Route>
        </Switch>
      </Router>
    );
  }
}

loginpage.tsx:

import * as React from "react";
import { Component, MouseEvent } from "react";
import { RouteComponentProps } from "react-router";
import { withRouter } from "react-router-dom";

interface State {
  isAuthenticated: boolean;
}

type PropsType = RouteComponentProps<any> & {
  isAuthenticated: boolean;
  history: any;
  location: any;
  match: any;
};

export class Login extends Component<PropsType> {
  constructor(props: PropsType, context?: any) {
    super(props, context);
    this.state = { isAuthenticated: false };
  }

  private login(e?: MouseEvent<HTMLInputElement>) {
    console.log("Logging in...");
    this.setState({ isAuthenticated: true });
  }

  public render() {
    console.log("Is authenticated: " + this.props.isAuthenticated);
    if (this.props.isAuthenticated) {
      this.props.history.push("/secret");
    }

    return (
      <div className="login">
        <br />
        <input type="button" value="Log in" onClick={e => this.login(e)} />
      </div>
    );
  }
}

export default withRouter(Login);

secretpage.tsx:

import * as React from "react";
import { Component } from "react";

export class SecretPage extends Component<{}, {}> {
  public render() {
    return (
      <div className="secretPage">
        <h1>Welcome to secret page</h1>
      </div>
    );
  }
}

Ответы [ 2 ]

0 голосов
/ 31 января 2020

ПРИМЕЧАНИЕ : Это не (прямой) ответ на ваш вопрос. Игнорируйте это, если вам нужен только прямой ответ.

Но я чувствую, что создание Public & Private маршрутов путем создания простой оболочки вокруг маршрута может помочь решить вашу проблему элегантным способом!

Есть так много статей по этому поводу, и я нашел это в google https://tylermcginnis.com/react-router-protected-routes-authentication/

Не стесняйтесь найти другой простой учебник, если можете.

0 голосов
/ 30 января 2020

Похоже, вы установили isAuthenticated в значение false, когда передаете эту опору компоненту <Login />. И затем вы пытаетесь использовать это состояние в компоненте <Login />. Было бы лучше, если бы вы подняли свое состояние, чтобы жить в компоненте <App />, а затем передали его в <Login /> через опору.

Это может выглядеть так: App.tsx

this.state = { isAuthenticated: false };

private login(e?: MouseEvent<HTMLInputElement>) {
  console.log("Logging in...");
  this.setState({ isAuthenticated: true });
}

if (this.props.isAuthenticated) {
  this.props.history.push("/secret");
}

<Login
  history={null}
  location={null}
  match={null}
  isAuthenticated={this.state.isAuthenticated}
  login={this.login}
/>

И в компоненте вместо запуска функции, которая была там, вы запускаете ту, которая теперь вместо этого передается.

<input type="button" value="Log in" onClick={() => this.props.login} />

...