React组件间数据传递:从子组件向父组件通信的最佳实践


React组件间数据传递:从子组件向父组件通信的最佳实践

本文详细介绍了在react应用中,如何实现子组件向父组件传递数据。通过利用react的单向数据流特性,结合回调函数作为props和父组件的状态管理,可以安全有效地将子组件(如表单输入)的数据传递给父组件,进而触发数据请求等逻辑。

在React应用开发中,组件之间的数据流动是核心概念之一。常见的场景是父组件向子组件传递数据(通过props),但当子组件需要将其内部状态或事件产生的数据反馈给父组件时,就需要采用特定的模式。本文将以一个具体的例子,讲解如何将子组件InputField中的用户输入值传递给父组件App,并用于API请求。

理解React的数据流

React推崇单向数据流(Unidirectional Data Flow)。这意味着数据通常从父组件流向子组件。如果子组件需要影响父组件的状态,它不能直接修改父组件的变量。相反,子组件应该通过调用父组件传递给它的函数(作为props)来通知父组件进行状态更新。这种模式被称为“提升状态”(Lifting State Up)或“回调函数模式”。

实现子组件向父组件传递数据

我们将通过以下步骤实现数据传递:

  1. 修改子组件InputField,使其接受一个回调函数作为props。
  2. 在InputField的事件处理函数中,调用这个回调函数,并传入需要传递的数据。
  3. 修改父组件App,定义一个状态来存储从子组件接收到的数据。
  4. 在App中定义一个函数,作为回调函数传递给InputField。
  5. 在App的useEffect中,监听这个状态的变化,并触发相应的API请求。

1. 修改子组件:InputField.js

首先,我们需要让InputField组件能够接受一个名为onSubmit的prop,这个prop将是一个函数。当用户提交表单时,handleSubmit函数会获取输入值inputVal,然后调用这个onSubmit prop,并将inputVal作为参数传递出去。

// InputField.js
export default function InputField({ onSubmit }) { // 接受 onSubmit prop
  function handleSubmit(e) {
    e.preventDefault(); // 阻止浏览器重新加载页面

    const form = e.target;
    const inputVal = form.myInput.value; // 获取输入框的值

    console.log("Input value from child:", inputVal);

    // 调用父组件传入的回调函数,并将输入值传递给它
    if (onSubmit) {
      onSubmit(inputVal); 
    }
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <input name="myInput" id="adress-field" placeholder="Enter address" autoComplete="on" />
      <button type="submit" id="adress-button">Send</button>
    </form>
  );
}

注意事项:

  • InputField现在是一个受控组件,它通过props接收行为。
  • onSubmit是一个约定俗成的prop名,表示当子组件内部发生“提交”事件时,父组件应该执行的逻辑。

2. 修改父组件:App.js

接下来,我们需要在App组件中:

  • 使用useState定义一个状态变量,例如searchValue,用于存储从InputField接收到的地址值。
  • 定义一个函数handleSearchSubmit,它将作为onSubmit prop传递给InputField。当InputField调用onSubmit时,handleSearchSubmit会被执行,并更新searchValue状态。
  • 将InputField组件正确地渲染到DOM中,并传递handleSearchSubmit作为其onSubmit prop。
  • 修改useEffect,使其依赖于searchValue状态,并在searchValue更新时触发API请求。
// App.js
import './App.css';
import AccountNumber from "./components/AccountNumber";
import InputField from "./components/InputField";
import { useEffect, useState } from "react";

function App() {
  // 状态用于存储从InputField接收到的搜索值
  const [searchValue, setSearchValue] = useState(''); // 初始化为空字符串,避免首次渲染时请求 'null'

  // token fetch 相关的状态
  const [tokens, setTokens] = useState([]);
  const [loading, setLoading] = useState(false);

  // 定义一个回调函数,用于接收InputField传递过来的值
  const handleSearchSubmit = (val) => {
    setSearchValue(val); // 更新searchValue状态
  };

  // useEffect 钩子用于处理副作用,例如数据获取
  useEffect(() => {
    // 只有当 searchValue 有效时才进行数据请求
    if (searchValue) { 
      setLoading(true);
      fetch(`https://api.multiversx.com/accounts/${searchValue}/tokens`)
        .then(response => response.json())
        .then(json => setTokens(json))
        .catch(error => {
          console.error("Error fetching tokens:", error);
          setTokens([]); // 请求失败时清空或重置tokens
        })
        .finally(() => {
          setLoading(false);
        });
    } else {
      // 如果 searchValue 为空,可以清空tokens或显示提示
      setTokens([]);
      setLoading(false);
    }
    console.log("Current tokens state:", tokens); // 注意:这里可能打印的是旧的tokens状态
  }, [searchValue]); // 依赖数组中包含 searchValue,当其改变时重新运行 effect

  function round(nr, ten) {
    return Math.round(nr * ten) / ten;
  }

  function numberWithSpaces(nr) {
    return nr.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
  }

  return (
    <content className="content">
        <div className="up-side">
            <div className="account-number-box">
                <p id="p-account-number">Total number of accounts</p>
                <p id="account-number"><AccountNumber/></p>
            </div>
            <div className="adress-search">
                {/* 正确地渲染 InputField 组件,并传递回调函数 */}
                <InputField onSubmit={handleSearchSubmit} /> 
            </div>
            {/* 可以显示当前的搜索值以供调试 */}
            <p>Current Search Value: {searchValue}</p>
        </div>
        <div className="down-side">
            <table className="Token-section-output">
              {loading ? (
                <div>Loading...</div>
              ) : (
                <>
                  <h1>Tokens</h1>
                  <table className='Token-section-output' border={0}>
                    <tr className='token-row-type'>
                      <th className='token-column'>Name</th>
                      <th className='center-column'>Price</th>
                      <th>Hold</th>
                    </tr>
                    <tr className="space20"/>

                    {tokens.map(token => (
                      <tr className='token-row' key={token.id}>
                        <td className='token-column'>
                        @@##@@ 
                          <p>{token.name}</p>
                    <div class="aritcle_card">
                        <a class="aritcle_card_img" href="/ai/1275">
                            <img src="https://img.php.cn/upload/ai_manual/001/431/639/68b6da8ca7356656.jpg" alt="Facetune">
                        </a>
                        <div class="aritcle_card_info">
                            <a href="/ai/1275">Facetune</a>
                            <p>一款在线照片和视频编辑工具,允许用户创建AI头像</p>
                            <div class="">
                                <img src="/static/images/card_xiazai.png" alt="Facetune">
                                <span>109</span>
                            </div>
                        </div>
                        <a href="/ai/1275" class="aritcle_card_btn">
                            <span>查看详情</span>
                            <img src="/static/images/cardxiayige-3.png" alt="Facetune">
                        </a>
                    </div>
                 
                        </td>
                        <td className='center-column'> <p>${round(token.price, 10000000)}</p> </td>
                        <td> 
                          <p>{round(token.balance / Math.pow(10, token.decimals), 10000000)}</p> 
                          <p className='token-hold'>${round(token.valueUsd, 10000000)}</p>
                        </td>
                      </tr>
                    ))}
                  </table>
                </>
              )}
            </table>
        </div>   
    </content>
  );
}

export default App;

关键点解析:

  • useState(''): searchValue被初始化为空字符串。这样,在组件首次渲染时,useEffect中的条件if (searchValue)将为假,从而避免了向https://api.multiversx.com/accounts//tokens这样的无效URL发起请求。
  • : 这是在React中渲染组件的正确方式。切勿直接调用InputField()函数,因为那样会绕过React的组件生命周期和状态管理机制。
  • useEffect依赖数组[searchValue]: 这是至关重要的。它告诉React,只有当searchValue的值发生变化时,才重新运行useEffect内部的代码。这确保了每次用户提交新的地址时,都会触发一次新的数据请求。

总结与最佳实践

通过上述步骤,我们成功地实现了从子组件InputField向父组件App传递数据,并利用该数据触发API请求。这种模式是React中处理组件间通信的常见且推荐的方式。

核心概念回顾:

  • 单向数据流: 数据从父组件流向子组件。子组件通过回调函数通知父组件更新状态。
  • 状态提升: 当多个组件需要共享或响应同一个数据时,将该数据提升到它们最近的共同父组件中管理。
  • 回调函数作为Props: 父组件定义一个函数,并将其作为prop传递给子组件。子组件在特定事件发生时调用这个函数,将数据传回父组件。
  • useState: 用于在函数组件中声明和管理状态。
  • useEffect: 用于处理组件的副作用,如数据获取、订阅或手动更改DOM。它的依赖数组决定了何时重新运行副作用。

遵循这些原则,可以构建出结构清晰、可维护性强的React应用。

React组件间数据传递:从子组件向父组件通信的最佳实践

以上就是React组件间数据传递:从子组件向父组件通信的最佳实践的详细内容,更多请关注其它相关文章!


# css  # 输入框  # 饰品营销渠道推广工作  # seo关键词查询平台  # 平安建设的网站有哪些  # seo关键词排名优化服务商  # 吉林网站推广和内容运营  # seo中关键词  # 怎么做珠宝营销推广方案  # seo检测外包  # 郑州化妆品营销推广招聘  # 漳州网站建设与开发招聘  # 使其  # 并将  # 首次  # 为空  # 一个函数  # 这是  # 是一个  # 从子  # 回调  # 应用开发  # 回调函数  # app  # 浏览器  # json  # js  # react 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894 】


相关推荐: 快递优选如何查优选物流_快递优选专属物流渠道查询与配送时效  J*a里如何处理ArithmeticException并防止除零_算术异常防护策略解析  蜻蜓FM如何设置移动流量播放  B站怎么快速升级 B站用户等级提升攻略【详解】  视频号视频怎么免费保存到相册?保存到相册需要注意什么?  《鹿路通》退余额方法  利用Flexbox实现图片元素的二维布局:2x2网格排列指南  Python测试中模块导入路径解析的最佳实践  手机雨课堂网页版入口免登录 雨课堂网页版可点击直接进入  抖音猜你想搜能说明对方搜过吗  composer 提示 "requires ext-soap" 缺少 SOAP 扩展怎么办?  快递查询,一键速查  Win11怎么录屏_Windows 11自带Xbox Game Bar录制视频  国际经济与贸易就业方向解析  《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊  电脑桌面图标怎么变大变小_Windows个性化设置第一课【新手入门】  Golang如何测试结构体方法_Golang reflect方法测试与调用技巧  《虎扑》取消评分记录方法  解决Windows上Composer PATH变量冲突导致的命令无法识别问题  WooCommerce 购物车:始终显示所有交叉销售商品  composer licenses 命令:如何检查项目依赖的许可证?  Pydantic 中“schema”字段命名冲突的解决方案  PHP页面重载后变量状态保持:实现用户档案连续浏览的教程  《edge浏览器》关闭翻译功能方法  Leaflet地图弹出窗口图片动态显示:避免缺失图标的专业指南  第五人格PC版怎么避免被封号_第五人格PC版防封号注意事项  Flask 应用中图片动态更新与上传:实现客户端定时刷新与服务器端文件管理  sublime如何配置PHP开发环境_在sublime中运行与调试PHP代码  优化 WooCommerce 产品价格显示与自定义短代码集成  秋风萧瑟洪波涌起中的萧瑟指的是什么  电子白板帮助菜单使用指南  POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩  在J*a里什么是行为抽象_抽象行为对代码复用的提升作用  《咸鱼之王》新版孙坚技能解析  小红书网页版首页入口 小红书网页版电脑端官方登录链接  中通快递官网指定查询 中通快递单号查询平台入口  QQ邮箱官方登录页_腾讯出品安全稳定的邮箱服务  《三国:谋定天下》平民全阶段通用阵容  动漫之家观看全集库 动漫之家免费资源网地址  Sublime怎么格式化HTML代码_Sublime前端代码美化插件使用指南  解决C#跨线程访问XML对象的异常 安全的并发XML处理模式  鲁班大师乓乓皮肤获取方法  《长生:天机降世》火塔小怪大全  优化CSS动画与J*aScript定时器协同:构建稳定Toast提示  Selenium自动化:利用键盘模拟解决复杂日期输入框输入问题  《王者荣耀世界》英雄获取攻略  Golang如何操作指针参数_Go pointer参数传递规则  msn官方入口2025登录 msn官网2025直达首页入口  斯宾塞称XGP云游戏“蒸蒸日上”:正在构建一个游戏从未如此唾手可得的未来  mysql离线安装后如何启动_mysql离线安装完成后启动服务的方法 

 2025-10-13

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.