You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:45:39