React中如何在onSubmit事件提取表单数据并实现组件传参?
问题解答
1. 提取两个输入框的数据
有两种常用的实现方式,根据你的需求选择即可:
方式一:受控组件(推荐,适合需要实时校验/联动的场景)
通过React状态管理输入框的值,绑定onChange事件实时更新状态,提交时直接读取状态值:
import { useState } from 'react'; function PlayerSearch() { // 初始化状态存储输入值 const [apiKey, setApiKey] = useState(''); const [playerName, setPlayerName] = useState(''); const handleSubmit = (e) => { e.preventDefault(); // 直接从state中获取输入数据 console.log('API密钥:', apiKey); console.log('玩家名称:', playerName); // 这里添加调用Riot API的逻辑 }; return ( <form onSubmit={handleSubmit}> <div> <label>API密钥:</label> <input type="text" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="输入24小时API密钥" /> </div> <div> <label>玩家名称:</label> <input type="text" value={playerName} onChange={(e) => setPlayerName(e.target.value)} placeholder="输入目标玩家名称" /> </div> <button type="submit">查询玩家信息</button> </form> ); }
方式二:非受控组件(适合无需实时处理输入的场景)
使用useRef获取输入框DOM元素,提交时读取元素的value属性:
import { useRef } from 'react'; function PlayerSearch() { // 创建ref绑定到输入框 const apiKeyRef = useRef(null); const playerNameRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); // 从ref中提取输入数据 const apiKey = apiKeyRef.current.value; const playerName = playerNameRef.current.value; console.log('API密钥:', apiKey); console.log('玩家名称:', playerName); // 这里添加调用Riot API的逻辑 }; return ( <form onSubmit={handleSubmit}> <div> <label>API密钥:</label> <input type="text" ref={apiKeyRef} placeholder="输入24小时API密钥" /> </div> <div> <label>玩家名称:</label> <input type="text" ref={playerNameRef} placeholder="输入目标玩家名称" /> </div> <button type="submit">查询玩家信息</button> </form> ); }
2. 拆分组件并通过Props传递数据优化结构
完全可以拆分组件,按照单一职责原则将输入收集、API请求、结果展示拆分为独立组件,通过Props传递数据,让代码结构更清晰、可维护性更强。
示例拆分方案
组件1:PlayerSearchForm(负责收集用户输入)
import { useState } from 'react'; function PlayerSearchForm({ onSearch }) { const [apiKey, setApiKey] = useState(''); const [playerName, setPlayerName] = useState(''); const handleSubmit = (e) => { e.preventDefault(); // 校验输入后,将数据通过回调传递给父组件 if (apiKey.trim() && playerName.trim()) { onSearch({ apiKey, playerName }); } }; return ( <form onSubmit={handleSubmit}> <div> <label>API密钥:</label> <input type="text" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="输入24小时API密钥" /> </div> <div> <label>玩家名称:</label> <input type="text" value={playerName} onChange={(e) => setPlayerName(e.target.value)} placeholder="输入目标玩家名称" /> </div> <button type="submit" disabled={!apiKey.trim() || !playerName.trim()}>查询玩家信息</button> </form> ); } export default PlayerSearchForm;
组件2:PlayerInfo(负责API请求和结果展示)
import { useState, useEffect } from 'react'; function PlayerInfo({ apiKey, playerName }) { const [playerData, setPlayerData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // 当apiKey或playerName变化时触发API请求 useEffect(() => { if (!apiKey || !playerName) return; const fetchPlayerData = async () => { setLoading(true); setError(null); try { // 替换为实际的Riot API接口地址 const response = await fetch( `https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/${encodeURIComponent(playerName)}?api_key=${apiKey}` ); if (!response.ok) throw new Error('请求失败,请检查API密钥和玩家名称'); const data = await response.json(); setPlayerData(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchPlayerData(); }, [apiKey, playerName]); // 根据状态渲染不同内容 if (loading) return <p>加载中...</p>; if (error) return <p className="error">错误: {error}</p>; if (!playerData) return null; return ( <div className="player-info"> <h3>玩家信息</h3> <p>召唤师名称: {playerData.name}</p> <p>召唤师等级: {playerData.summonerLevel}</p> <p>召唤师ID: {playerData.id}</p> {/* 可添加更多需要展示的字段 */} </div> ); } export default PlayerInfo;
主组件:PlayerSearch(组合两个子组件)
import { useState } from 'react'; import PlayerSearchForm from './PlayerSearchForm'; import PlayerInfo from './PlayerInfo'; function PlayerSearch() { const [searchParams, setSearchParams] = useState(null); return ( <div className="player-search-container"> <PlayerSearchForm onSearch={(params) => setSearchParams(params)} /> {/* 当有搜索参数时,渲染结果组件并传递数据 */} {searchParams && ( <PlayerInfo apiKey={searchParams.apiKey} playerName={searchParams.playerName} /> )} </div> ); } export default PlayerSearch;
这种拆分方式让每个组件只负责一项功能,后续修改输入逻辑或展示逻辑时无需改动其他部分,复用性和可维护性大幅提升。
内容的提问来源于stack exchange,提问作者lamsmallsmall
相关产品推荐
相关产品推荐

