【问题标题】:React & React Router, Unable to call the parent functionReact & React Router,无法调用父函数
【发布时间】:2020-01-27 16:51:18
【问题描述】:

我正在开发一个 React 应用程序(使用 react-router-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 不是函数。我究竟做错了什么?欢迎任何帮助。

【问题讨论】:

  • 是的,没错。 Login 类没有 userHasAuthenticated 的概念。您需要将其作为来自App 的道具传递给Login
  • 这是因为你的Login 组件不知道this.userHasAuthenticated(true); 是什么意思。它没有userHasAuthenticated 的声明。您需要将其传递给该组件
  • 我试图通过以下方式做到这一点: 。这不是正确的方法吗?
  • 那么它附加到props而不是this。将其从props 取下,将其附加到constructorconstructor 中的thisprops

标签: javascript reactjs react-router


【解决方案1】:

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);

【讨论】:

  • 谢谢。它稍作修改即可工作:'export default parentProps => } /> } /> } /> ; '
猜你喜欢
  • 2019-05-12
  • 2020-02-17
  • 2023-01-22
  • 2017-12-22
  • 2022-11-04
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 2020-02-15
相关资源
最近更新 更多