记录React中父组件使用调用子组件方法

日常开发中组件之间的通信是比较经常需要使用到的一点,react的组件数据流方式是从父组件传到子组件,如果子组件需要用到父组件的方法,可以在父组件之间通过props传递,子组件进行调用。但是在业务上有时候无法避免需要用到子组件调用父组件的方法的场景

子组件访问父组件的方法

子组件要访问父组件的方法就比较简单,可以直接通过props来传递父组件的方法,子组件通过props向上调用的方式来访问父组件的函数,直接调用,下面是一些举例的代码。

js 复制代码
const ParentComponent = () => {
	const handleState = (value) => {
	}
	return (
		<ChildComponent getState={handleState}/>
	)
}

const ChildComponent = (props) => {
	const callMethod = () => {
		props.getState('123')
	}
	return (
		<Button onClick={callMethod}>调用父组件方法</Button>
	)
}

父组件访问子组件

用下面的方法来获取子组件的方法,创建一个ref,和vue访问子组件的方式类似,都是通过ref的方法

js 复制代码
import React, { Component } from 'react';
const inputRef = useRef<Input | null>(null);
<div
  className={classNames(className, styles.headerSearch)}
  onClick={() => {
    setSearchMode(true);
    if (searchMode && inputRef.current) {
      inputRef.current.focus();
    }
  }}
  onTransitionEnd={({ propertyName }) => {
    if (propertyName === 'width' && !searchMode) {
      if (onVisibleChange) {
        onVisibleChange(searchMode);
      }
    }
  }}
>
<Input
  size="small"
  ref={inputRef}
  defaultValue={defaultValue}
  aria-label={placeholder}
  placeholder={placeholder}
  onKeyDown={(e) => {
    if (e.key === 'Enter') {
      if (restProps.onSearch) {
        restProps.onSearch(value);
      }
    }
  }}
  onBlur={() => {
    setSearchMode(false);
  }}
/>

但是上面的方法尝试过后会发现可能存在inputRef.current等于undefined的情况,用起来不是很方便,所以建议尝试下面的方法

useImperativeHandle

useImperativeHandle 是 React 中的一个自定义 Hook,它允许函数式组件与父组件之间的通信。通常情况下,React 的数据流是自上而下的,但有时候需要从子组件向父组件传递数据或方法。useImperativeHandle 就是一个比较方便实现的方法

javascript 复制代码
javascriptCopy code
import React, { useRef, useImperativeHandle, forwardRef } from 'react';

// 子组件
const ChildComponent = forwardRef((props, ref) => {
  const internalRef = useRef();

  // 在子组件中定义需要暴露给父组件的方法或数据
  useImperativeHandle(ref, () => ({
    someFunction: () => {
      // 这个函数可以在父组件中被调用
      console.log('Function from ChildComponent called');
    },
    someData: 'Data from ChildComponent',
  }));

  return (
    <div>
      {/* 子组件的内容 */}
    </div>
  );
});

// 父组件
function ParentComponent() {
  const childRef = useRef();

  const handleButtonClick = () => {
    // 在父组件中调用子组件暴露的函数
    childRef.current.someFunction();
  }

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleButtonClick}>Call ChildComponent Function</button>
    </div>
  );
}

在上面的示例中,useImperativeHandle 用于子组件 ChildComponent,并通过 forwardRef 使得父组件能够访问 childRef.current,调用子组件的函数。父组件可以在需要时通过 childRef.current 访问子组件的暴露接口,调用函数或访问数据。

总结

其实react开发中并不赞成去用ref来访问子组件的方法,因为使用ref需要父组件知道子组件内部的解构和方法命名,这样就无法遵从解耦的原则,组件会变得更加的难以重用和维护,并且react推荐组件的独立性和封装性,只通过props来进行通信,直接访问子组件会破坏封装性,导致需要配合父组件来修改子组件

并且组件整个替换或者需要修改内部逻辑的时候,可能需要同时修改子组件和父组件的方法,会大大的增加在开发中的维护复杂度,在开发中应该尽量避免用父组件来访问子组件的方法

如果觉得有趣或有收获,请关注我的更新,给个喜欢和分享。您的支持是我写作的最大动力!

往期好文推荐

相关推荐
花间相见6 分钟前
【终端效率工具01】—— Yazi:Rust 编写的现代化终端文件管理器,告别繁琐操作
前端·ide·git·rust·极限编程
Bug终结者_8 分钟前
别只会写 Java 了!LangChain4J 带你弯道超车 AI 赛道
后端·langchain·ai编程
Oneslide14 分钟前
MySQL性能排查实战:大量Sleep空闲连接导致数据库写入缓慢解决方案
后端
|晴 天|15 分钟前
我如何用Vue 3打造一个现代化个人博客系统(性能提升52%)
前端·javascript·vue.js
风止何安啊23 分钟前
网页都知道要双向握手才加载!从 URL 到页面渲染,单向喜欢连 DNS 都解析不通
前端·javascript·面试
太极OS29 分钟前
给 AI Skill 做 CI/CD:GitHub + ClawHub + Xiaping 同步发布实战
前端
你_好29 分钟前
Chrome 内置了 AI 工具协议?WebMCP 抢先体验 + 开源 DevTools 全解析
前端·mcp
GISer_Jing30 分钟前
LangChain.js + LangGraph.js 前端AI开发实战指南
前端·javascript·langchain
正在发育ing__33 分钟前
从源码看vue的key和状态错乱的patch
前端
码界奇点1 小时前
基于Spring Boot的前后端分离商城系统设计与实现
java·spring boot·后端·java-ee·毕业设计·源代码管理