React & React Router, Невозможно вызвать родительскую функцию - PullRequest
0 голосов
/ 27 января 2020

Я занимаюсь разработкой приложения React (с реагирующим маршрутизатором-dom) и пытаюсь вызвать функцию, определенную в родительском компоненте App. Родительский компонент был определен следующим образом:

import React, { Component, Fragment } from 'react';
import { Link, NavLink } from 'react-router-dom';
import Routes from './components/routes';
import { withRouter } from 'react-router';
import { Auth } from "aws-amplify";
import Login from './components/Login';
import logo from './logo.svg';
import './App.css';


class App extends Component {
  constructor(props) {
    super(props);
    this.userHasAuthenticated = this.userHasAuthenticated.bind(this);
    this.state = {
      isAuthenticated: false
    }
  }

  userHasAuthenticated = (value) => {
    this.setState({ isAuthenticated: value });
  }

  handleLogout = async event => {
    await Auth.signOut();
    this.userHasAuthenticated(false);
    this.props.history.push("/");
  }

  async componentDidMount() {
    try {
      await Auth.currentSession();
      this.userHasAuthenticated(true);
      this.props.history.push("/chat");
    } catch(e) {
      if (e !== 'No current user') {
        alert(e);
      }
    }
  }

  render() {
    return (
      <Fragment>
        <div className="navbar navbar-expand-lg navbar-light bg-light">
            <Link to="/" className="navbar-brand" href="#"><h1>Sample App</h1></Link>
              <div className="collapse navbar-collapse" id="navbarNav">
                  <ul className="navbar-nav">
                    {this.state.isAuthenticated ? 
                      <Fragment>
                        <li className="nav-item">
                          <NavLink to="/chat" className="nav-link">Chat</NavLink>
                        </li>
                        <li className="nav-item">
                          <NavLink to="/" className="nav-link" onClick={this.handleLogout}>Logout</NavLink>
                        </li>
                      </Fragment> : 
                      <Fragment>
                        <li className="nav-item">
                          <NavLink to="/" className="nav-link">Login</NavLink>
                        </li>
                        <li className="nav-item">
                          <NavLink to="/Signup" className="nav-link">Signup</NavLink>
                        </li>
                      </Fragment>
                    } 
                  </ul>
              </div>
        </div>
        <Routes userHasAuthenticated= { this.userHasAuthenticated } isAuthenticated = { this.state.isAuthenticated }/>
      </Fragment>
    );
  }
}

export default withRouter(App);

Предполагается, что компонент входа в систему аутентифицирует пользователя, обновляет состояние (используя функцию hasUserAuthenticated, определенную в родительском компоненте) и перенаправляет пользователя на другую страницу.

import React, { Component } from "react";
import { FormGroup, FormControl, FormLabel, Button } from "react-bootstrap";
import { Auth } from "aws-amplify";

export default class Login extends Component {
    constructor(props) {
        super(props);
        this.state = {
            email: "",
            password: ""
        };
    }

    validateForm() {
        return this.state.email.length > 0 && this.state.password.length>0;
    }

    handleChange = event => {
        this.setState({
                [event.target.id]: event.target.value
            });
    }

    handleSubmit = async event => {
        event.preventDefault();
        try {
            await Auth.signIn(this.state.email, this.state.password);
            this.userHasAuthenticated(true);
            this.props.history.push("/chat");
        } catch (e) {
            alert(e.message);
        }
    }

    render() {
        return (
            <div className="Home">
                <div className="col-md-4"> 
                    <form onSubmit={this.handleSubmit}>
                        <FormGroup controlId="email">
                            <FormLabel>Email</FormLabel>
                            <FormControl
                                autoFocus
                                type="email"
                                value={this.state.email}
                                onChange={this.handleChange}
                            />
                        </FormGroup>
                        <FormGroup controlId="password" >
                            <FormLabel>Password</FormLabel>
                            <FormControl
                                value={this.state.password}
                                onChange={this.handleChange}
                                type="password"
                            />
                        </FormGroup>
                        <Button type="submit">
                        Login
                        </Button>
                    </form>
                </div>
            </div>
        );
    }
}

Компонент «Мои маршруты» выглядит следующим образом:

import React from 'react';
import Signup from './Signup';
import Login from './Login';
import NotFound from './NotFound';
import chat from './chat';

import { Route, Switch } from "react-router-dom";

export default ( { childProps } ) =>
<Switch>
    <Route exact path ="/" component={Login} props={childProps}/>
    <Route exact path ="/Signup" component={Signup} props={childProps}/>
    <Route exact path ="/chat" component={chat} props={childProps}/>
    <Route component={NotFound} />
</Switch>;

Однако приложение выдает ошибку, говоря, что this.userHasAuthenticated не является функцией. Что я делаю неправильно? Любая помощь будет приветствоваться.

1 Ответ

1 голос
/ 27 января 2020

В Routes.js вам нужны эти изменения

import React from 'react';
import Signup from './Signup';
import Login from './Login';
import NotFound from './NotFound';
import Chat from './chat';

import { Route, Switch } from "react-router-dom";

export default parentProps =>
<Switch>
    <Route exact path ="/" render={(props => <Login {...props} {...parentProps} />) />
    <Route exact path ="/Signup" render={(props => <Signup {...props} {...parentProps} />) />
    <Route exact path ="/chat" render={(props => <Chat {...props} {...parentProps} />) />
    <Route component={NotFound} />
</Switch>;

А также в Login или любом дочернем компоненте используйте this.props.userHasAuthenticated(true); вместо this.userHasAuthenticated(true);

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