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

React19中如何通过引用调用组件方法?旧版React16的refs用法无法兼容

React19中如何通过引用调用组件方法?旧版React16的refs用法无法兼容

我来帮你解决这个问题!你遇到的核心问题是函数组件中没有this,而且React16.3之后就废弃了旧的字符串refs写法(比如this.refs.toast),现在推荐使用useRef(函数组件)或createRef(类组件)来获取组件引用。结合你的代码,我会一步步教你修改。

问题根源拆解

  1. 你的App是函数组件,函数组件中不存在this,所以this.refs自然会是undefined。
  2. 旧的字符串ref(如<Toast ref="toast"/>)早已被废弃,React不再支持这种方式访问组件实例。
  3. 类组件的实例方法(比如Toast的erro)可以通过ref.current直接访问(如果是函数组件则需要额外处理)。

解决方案:用useRef重构App组件

我们只需要修改App组件的代码,用useRef获取Toast组件的实例,然后通过实例调用erro方法。

修改后的App组件代码

import React, { useRef } from 'react';
import './App.css';
import Header from './components/Header/Header.tsx';
import NovoUsuario from './components/NovoUsuário/NovoUsuario.tsx';
import Toast from './components/Toast/Toast.tsx'

function App() {
  // 创建ref对象,用于存储Toast组件的实例
  // 如果你用TypeScript,加上类型约束更安全;不用TS的话可以写成const toastRef = useRef(null);
  const toastRef = useRef<InstanceType<typeof Toast>>(null);

  return (
    <div>
      <Header />
      {/* 重构erro回调:通过ref.current调用Toast的erro方法 */}
      {/* 用可选链?.避免组件未挂载时current为null的错误 */}
      <NovoUsuario erro={(msg) => toastRef.current?.erro(msg)} />
      {/* 将ref绑定到Toast组件上 */}
      <Toast ref={toastRef} />
    </div>
  );
}

export default App;

关键修改点说明

  1. 创建useRef对象:const toastRef = useRef(null)会创建一个可以存储组件实例的引用对象,初始值为null。
  2. 绑定ref到Toast组件:给<Toast>组件添加ref={toastRef}属性,当Toast组件挂载后,toastRef.current就会指向Toast的类实例。
  3. 调用实例方法:用toastRef.current?.erro(msg)代替旧的this.refs.toast.erro(msg),可选链?.能防止Toast还没挂载时current为null导致的报错。

额外优化:如果把Toast转为函数组件

如果后续你想把Toast类组件转为函数组件(React19更推荐函数组件+钩子的写法),需要用forwardRef和useImperativeHandle来暴露内部方法,示例如下:

import React, { forwardRef, useImperativeHandle } from "react";
import { ToastContainer, toast } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'

// 用forwardRef允许父组件传递ref
const Toast = forwardRef((props, ref) => {
  const sucesso = (msg: string) => {
    toast.success(msg)
  }

  const info = (msg: string) => {
    toast.info(msg)
  }

  const erro = (msg: string) => {
    toast.error(msg)
  }

  // 用useImperativeHandle暴露给父组件需要调用的方法
  useImperativeHandle(ref, () => ({
    sucesso,
    info,
    erro
  }), []) // 依赖为空数组,只初始化一次

  return(
    <ToastContainer
      position="bottom-center"
      autoClose={5000}
      hideProgressBar={true}
      closeOnClick
      pauseOnHover
    />
  )
})

export default Toast

为什么Context不适合这里?

你提到尝试了Context但没成功,其实Context是用来跨多层组件共享状态的,而你的场景是父组件(App)直接访问子组件(Toast)的方法,用ref是最直接高效的方式,完全不需要用到Context。

备注:内容来源于stack exchange,提问作者Pedro Rodrigues

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 15:13:08