记录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来进行通信,直接访问子组件会破坏封装性,导致需要配合父组件来修改子组件

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

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

往期好文推荐

相关推荐
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
码农小旋风3 小时前
详解K8S--声明式API
后端
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js