React组件未接收到react-router props问题求助
解决React登录组件中
this.props为undefined且无法跳转的问题 我来帮你拆解下问题,然后给出几个实用的解决方案:
问题根源
- 函数组件不存在
this:你写的Login和Index都是函数组件,函数组件里没有this对象,所以this.props必然是undefined,得直接用props参数来获取属性。 - 路由props未向下传递:
Index组件是被Route直接渲染的,它能拿到路由相关的props(比如history),但你在Index里直接渲染Login/Home时,没把这些props传递给子组件,导致Login拿不到history。 - 回调函数的
this指向问题:你在fetch的.then(function(data) { ... })里用了普通函数,这里的this指向不是组件实例,就算有this.props也会出错,换成箭头函数就能解决这个问题。
解决方案一:使用useHistory钩子(推荐,函数组件最佳实践)
React Router v5及以上版本提供了useHistory钩子,让函数组件可以直接获取history对象,完全不需要依赖props传递:
修改Login组件:
import React from 'react' import { useHistory } from 'react-router-dom' // 导入useHistory钩子 const Login = () => { const history = useHistory(); // 获取history对象 let user, pass const login = e => { e.preventDefault(); fetch("http://localhost:3000/api/login", { method: "GET", headers: { "user": user.value, "pass": pass.value } }) .then(response => response.json()) .then(data => { // 换成箭头函数,避免this指向混乱 if (data.user) { localStorage.setItem("username", data.user) history.push("/"); // 直接调用history.push完成跳转 } else { console.log("Failed to get user") } }) } return( <div> <h1>Login</h1> <form onSubmit={login}> <label> Username: <input type="text" className="form-control col-md-12" ref = {node => user = node}/> </label> <label> Password: <input type="password" className="form-control col-md-12" ref = {node => pass = node}/> </label> <br /> <input type="submit" value="Submit" /> </form> </div> ) } export default Login
这个方案不需要修改Index组件,Login自己通过钩子就能拿到history,代码更简洁清晰。
解决方案二:手动传递路由props
如果你暂时不想用钩子,也可以通过手动传递props的方式解决:
- 修改
Index组件,接收并传递路由props:
import React from 'react' import Login from './Login' import Home from './Home' const Index = (props) => { // 接收Route传递的props if (localStorage.getItem("username")) { return <Home {...props} />; // 将所有props传递给Home组件 } else { return <Login {...props} /> // 将所有props传递给Login组件 } } export default Index
- 修改
Login组件,接收props并使用:
import React from 'react' const Login = (props) => { // 接收父组件传递的props let user, pass const login = e => { e.preventDefault(); fetch("http://localhost:3000/api/login", { method: "GET", headers: { "user": user.value, "pass": pass.value } }) .then(response => response.json()) .then(data => { // 用箭头函数避免this指向问题 if (data.user) { localStorage.setItem("username", data.user) props.history.push("/"); // 使用props中的history对象跳转 } else { console.log("Failed to get user") } }) } // 其余return部分保持不变 } export default Login
额外提示
- 实际项目中不建议用
GET方法传递用户名和密码,这会把敏感信息暴露在URL里,建议改成POST方法,把参数放在请求体中。 - 如果你的React Router是v6版本,
useHistory已经被useNavigate替代,用法类似:const navigate = useNavigate();,跳转时用navigate("/")。
内容的提问来源于stack exchange,提问作者user8808986
相关产品推荐
相关产品推荐

