Как мне создать PrivateRoute для компонента, который опирается на компонент состояния isAuth из (отдельного) класса Login? - PullRequest
0 голосов
/ 02 апреля 2020

Я довольно новичок в React, но я ломал голову над различными способами создания PrivateRoute весь день и не смог выяснить, как правильно аутентифицировать пользователя через мою форму входа.

Ниже приведен код моей маршрутизации, а также класс Login и функция PrivateRoutes (содержится в отдельном файле). Я подозреваю, что проблема, скорее всего, связана с моим отсутствием понимания относительно реквизита против переменных состояния и которое может быть передано родительским классам.

Вот файл маршрутизации:

import React, {Component} from 'react';
import './Style.css';
import ReactDOM from 'react-dom';

import {BrowserRouter, Route, Redirect, Switch} from 'react-router-dom';

import PublicLanding from './Pages/PublicLanding'
import AllClasses from './Pages/AllClasses'
import Classes from './Pages/Classes'
import Schools from './Pages/Schools'
import Home from './Pages/Home'
import Signup from './Pages/Signup'
import Login from './Pages/Login'
import NotFound from './Pages/NotFound'
import PrivateRoute from './Pages/PrivateRoute'

class App extends Component {

  render() {
    return(
      <BrowserRouter>
      <Switch>

      <Route exact path='/' component={PublicLanding}/>

      <Route exact path='/signup' render={() => (
          <Signup/>
      )}/>

      <Route exact path='/login' render={() => (
          <Login/>
      )}/>

      <Route exact path='/schools' render={() => (
          <Schools/>
      )}/>

      <Route exact path='/classes' render={() => (
          <AllClasses/>
      )}/>

      <Route exact path='/classes/:course_code' render={() => (
          <Classes/>
      )}/>

      <PrivateRoute exact path="/dashboard" component={Home}/>

      //generic path to render if none of the other work
      <Route path='*' render={() => (
        <NotFound/>
      )} />

      </Switch>
    </BrowserRouter>
    )
  }
}
export default App;

Это класс входа в систему:

import React, { Component } from 'react';
import { Switch, Route, Redirect } from 'react-router-dom';
import PrivateRoute from './PrivateRoute'

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: '',
      password: '',
      isEmail: false,
      warningText: '',
      invalidReason: '',
      isAuth: false
    };
  }

  login = () => {
    // make sure it's a valid email before checking the database
    if (this.state.isEmail) {
      var details = {
        'email': this.state.email,
        'password': this.state.password
      };

      const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&'); // Putting json into acceptable format to be read
      fetch('http://localhost:8888/authenticate', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
        },
        body: formBody
      }).then((response) => response.json())
      .then((responseJson) => {
        if(responseJson.page === "Home"){
           this.setState({
             isAuth: true
           });
        } else {
          this.setState({invalidReason: responseJson.error}, () => {
            this.invalidAuthentication();
          });
        }
      });
    } else {
      if (this.state.email + this.state.password === '') {
        this.setState({invalidReason: 'You need to enter a username and password'}, () => {
          this.invalidAuthentication();
        });

      } else {
        this.setState({invalidReason: 'Your credentials are incorrect.'}, () => {
          this.invalidAuthentication();
        });
      }
    }
  }

  invalidAuthentication = () => {
    alert(
      this.state.invalidReason,
      [
        {text: 'Ok'},
      ],
      {cancelable: false},
    );
  }

  invalidEmail = () => {
    this.setState({
      warningText: "Please enter a valid official school email address."
    })
  }

  verify = (email) => {
    this.setState({
      email:email
    });
    let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})/;
    if (reg.test(email) === false){
      this.invalidEmail();
    } else {
      this.setState({
        isEmail: true,
        warningText: ''
      });
    }
  }

  render() {
    if(this.state.isAuth) return (
      <PrivateRoute to="/dashboard" auth={this.state.isAuth}/>
    );
    return (
      <div className="render-events">
          <h1>Login</h1>
          <label>
          Username:
           <input type="text" placeholder="email@school.edu" onChange={(text) => this.verify(text.target.value)}/>
          </label>
          <label>
          Password:
          <input type="text" securetextentry="true" onChange={(text) => this.setState({password:text.target.value})}/>
         </label>
         <button onClick={() => this.login()}>
         Login
         </button>
      </div>
    );
  }
}
export default Login;

И, наконец, вот функция PrivateRoutes:

import React from 'react'
import { Route, Redirect } from 'react-router-dom';

const PrivateRoute = ({ component: Component, ...rest }) => (
    (props) => (
      <Route
        render={(props) =>
          props.isAuth === true ? <Component {...props} /> : <Redirect to="/login" />
        }
      />
    )
)

export default PrivateRoute;

Я был бы очень признателен за помощь в этом, поскольку я не нашел исчерпывающего объяснения того, как а) создать функцию входа в систему на экране маршрутизации (которая кажется неэффективной) или б) передать реквизит isAuth обратно. до моих маршрутов.

Заранее спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...