React如何将Authentication组件state传递至App.js及报错解决
问题修复方案
报错原因
TypeError: Cannot read properties of undefined (reading 'state') 报错源于两个核心错误:
- App是函数组件,不存在
this指向,你直接调用this.state时this为undefined,自然读取不到state属性 - 父子组件传值逻辑颠倒:你需要把父组件的更新方法传递给子组件,由子组件在拿到用户数据后主动调用该方法更新父组件状态,而非在传递方法时就直接执行
修复步骤
1. 修改App.js代码
核心修改路由中Authentication组件的传参逻辑,直接把setUserData方法传递给子组件,不要提前执行:
import Home from './pages/Home'; import Book from './pages/Book' import {Route, Switch} from 'react-router-dom'; import SavedBooks from './pages/SavedBooks'; import Header from './componens/Header'; import BookChapter from './pages/BookChapter'; import Authentication from './pages/Authentication'; import {useState} from "react"; function App(props) { // 初始值设为null更符合未登录状态 const [userData, setUserData] = useState(null); return ( <div> <Header/> <Switch> <Route exact path="/" render={(props) => <Home {...props} userData={userData}/>}/> <Route exact path="/book/:id" component={Book}/> <Route exact path="/savedbooks" component={SavedBooks}/> <Route exact path="/book/:id/chapter/:numero" component={BookChapter}/> {/* 直接传递setUserData方法,不要提前执行 */} <Route exact path="/authentication" render={(props) => <Authentication {...props} setUserData={setUserData}/> }/> </Switch> </div> ) } export default App;
2. 修改Authentication.js代码
首先接收父组件传递的setUserData方法,在登录/注册请求成功后调用该方法把用户数据同步到父组件,同时补全原代码缺失的事件处理函数:
import { useState } from "react" import MyButton from "../componens/myButton" import styles from "../style/authentication.module.css" import Spinner from "../componens/Spinner" import axios from "axios" // 接收父组件传递的setUserData const Authentication = ({setUserData}) =>{ const [email, setEmail] = useState("") const [password, setPassword] = useState("") const [loading, setLoading] = useState(false) const [registration, setRegistration] = useState(true) const [state, setState] = useState(null) let MyRegistration = null; // 补全缺失的邮箱输入处理函数 const handleEmail = (e) => { setEmail(e.target.value) } // 补全缺失的密码输入处理函数 const handlePassword = (e) => { setPassword(e.target.value) } // 补全缺失的登录注册切换函数 const changeMode = () => { setRegistration(!registration) } const handleSubmit = async (e) =>{ e.preventDefault() setLoading(true) try { const userKey = `AIzaSyCYe1XVuJVflRie0sf1y01RNrmQ77Dmp4Q` let urlAPI = `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${userKey}` if (!registration) { urlAPI = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${userKey}` } MyRegistration = await axios.post(urlAPI,{ email : email, password : password, returnSecureToken : true }) setState(MyRegistration) // 调用父组件传递的方法,把用户数据同步到App.js的userData setUserData(MyRegistration) setLoading(false); return MyRegistration } catch (error) { setLoading(false) console.log(error) } } return <div className={styles.formContainer}> <h1>Authentication</h1> <form onSubmit={handleSubmit} action=""> <p>Email</p> <input placeholder="Your email" type="email" value={email} onChange={handleEmail} /> <p>Password</p> <input placeholder="Your Password" type="password" value={password} onChange={handlePassword} /> {loading ? <Spinner/> : <MyButton title={registration ? 'sign up' : 'Sign in'} handleClickButton={handleSubmit} />} <MyButton title={registration ? 'Go to Sign in' : 'Go to sign up'} handleClickButton={changeMode}/> </form> </div> } export default Authentication;
修改完成后即可实现用户登录状态从Authentication组件到App组件的同步,你可以直接使用App里的userData判断用户登录状态,开放对应功能。
内容的提问来源于stack exchange,提问作者Cimo
相关产品推荐
相关产品推荐

