React中如何从子Input组件获取输入值并更新父组件状态
问题描述
我希望获取“Email Address”和“Password”两个输入框的值,并通过setEmail和setPassword来更新对应的状态,但不知道该如何从子组件的输入框中获取这些值?我移除了onChange事件,当前的硬编码值是用于测试的,但这让我疑惑该如何获取输入值。
父组件代码
import { useState } from "react" import Input from "./form/Input"; import { useNavigate, useOutletContext } from "react-router-dom"; const Login =() => { const [email,setEmail] = useState(""); const [password,setPassword] = useState(""); const {setJwtToken} = useOutletContext(""); const {setAlertClassName} = useOutletContext(""); const {setAlertMessage} = useOutletContext(""); const navigate = useNavigate(); const handleSubmit=(event)=>{ event.preventDefault(); console.log("email/password",email,password); let payload ={ email: email, password: password, } const requestOptions = { method: "POST", headers: { 'Content-Type':'application/json' }, credentials: 'include', body: JSON.stringify(payload) } fetch(`/authenticate`,requestOptions) .then((request)=> request.json()) .then((data) => { if(data.error) { setAlertClassName("alert-danger"); setAlertMessage(data.message); } else { setJwtToken(data.access_token); setAlertClassName("d-none"); setAlertMessage(""); navigate("/"); } }) .catch(error => { setAlertClassName("alert-danger"); setAlertMessage(error); }) } return ( <div className="col-md-6 offset-md-3"> <h2>Login</h2> <hr/> <form onSubmit={handleSubmit}> <Input title="Email Address" type="email" className="form-control" name="email" autoComplete="email-new" value="admin@example.com" /> <Input title="Password" type="password" className="form-control" name="password" autoComplete="password-new" value="secret" /> <Input type="submit" className="btn btn-primary" value="Login" /> </form> </div> ) } export default Login
子组件代码
import { forwardRef } from "react" const Input = forwardRef((props,ref)=> { return( <div className="mb-3"> <label htmlFor={props.name} className="form-lable"> {props.title} </label> <input type={props.type} className={props.className} id={props.id} ref={ref} name={props.name} placeholder={props.placeHolder} onChange={props.onChange} autoComplete={props.autoComplete} value={props.value} /> <div className={props.errorDiv}>{props.errorMsg}</div> </div> ) }) export default Input;
解决方案
你的子组件已经支持接收onChange属性并传递输入框的事件,只需要在父组件中添加状态更新的逻辑即可,下面提供两种常用实现方式:
方式1:独立处理每个输入框的变化
为邮箱和密码分别定义专属的事件处理函数,传递给对应的Input组件:
import { useState } from "react" import Input from "./form/Input"; import { useNavigate, useOutletContext } from "react-router-dom"; const Login =() => { const [email,setEmail] = useState("admin@example.com"); const [password,setPassword] = useState("secret"); const {setJwtToken} = useOutletContext(""); const {setAlertClassName} = useOutletContext(""); const {setAlertMessage} = useOutletContext(""); const navigate = useNavigate(); // 处理邮箱输入变化 const handleEmailChange = (e) => { setEmail(e.target.value); } // 处理密码输入变化 const handlePasswordChange = (e) => { setPassword(e.target.value); } const handleSubmit=(event)=>{ event.preventDefault(); console.log("email/password",email,password); // 原有提交逻辑保持不变 } return ( <div className="col-md-6 offset-md-3"> <h2>Login</h2> <hr/> <form onSubmit={handleSubmit}> <Input title="Email Address" type="email" className="form-control" name="email" autoComplete="email-new" value={email} onChange={handleEmailChange} /> <Input title="Password" type="password" className="form-control" name="password" autoComplete="password-new" value={password} onChange={handlePasswordChange} /> <Input type="submit" className="btn btn-primary" value="Login" /> </form> </div> ) } export default Login
方式2:通用处理函数(适用于多字段表单)
用一个对象管理所有表单状态,通过输入框的name属性匹配对应的状态字段,减少重复代码:
import { useState } from "react" import Input from "./form/Input"; import { useNavigate, useOutletContext } from "react-router-dom"; const Login =() => { const [formData, setFormData] = useState({ email: "admin@example.com", password: "secret" }); const {setJwtToken} = useOutletContext(""); const {setAlertClassName} = useOutletContext(""); const {setAlertMessage} = useOutletContext(""); const navigate = useNavigate(); // 通用输入变化处理函数 const handleInputChange = (e) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); } const handleSubmit=(event)=>{ event.preventDefault(); const { email, password } = formData; console.log("email/password",email,password); // 提交时直接使用formData作为payload即可 let payload = formData; // 原有提交逻辑保持不变 } return ( <div className="col-md-6 offset-md-3"> <h2>Login</h2> <hr/> <form onSubmit={handleSubmit}> <Input title="Email Address" type="email" className="form-control" name="email" autoComplete="email-new" value={formData.email} onChange={handleInputChange} /> <Input title="Password" type="password" className="form-control" name="password" autoComplete="password-new" value={formData.password} onChange={handleInputChange} /> <Input type="submit" className="btn btn-primary" value="Login" /> </form> </div> ) } export default Login
注意事项
- 必须将输入框的
value绑定到父组件的状态值,这样输入框会和状态双向同步,输入内容时状态会实时更新。 - 子组件无需修改,它已经实现了将输入框的
onChange事件传递给父组件的逻辑。
内容的提问来源于stack exchange,提问作者user63898
相关产品推荐
相关产品推荐

