【问题标题】:Can a (modern) React functional component expose a stateful method externally?(现代)React 功能组件可以在外部公开有状态方法吗?
【发布时间】:2021-12-27 22:41:30
【问题描述】:

我的 React 功能组件可以在外部公开一个可以访问内部状态的方法吗?

interface Inner {
  foo: string
}

function Inner(props: Inner) {
  const [foo, setFoo] = useState<string>(props.foo + "baz")
    
  function doTheThing() {
    console.log(`doin' that ${foo} thing`)
  }

  return <div>{props.foo}</div>
}

function Outer() {
  const inner = <Inner foo="bar" />

  return (
    <>
      <button onClick={() => inner.doTheThing()}>
        Do That Thing
      </button>
      {inner}
    </>
  )
}

这当然会给我一个错误:TypeError: inner.doTheThing is not a function

我可以使用类组件来公开这样的方法。但是有没有办法(用钩子?用 refs?)使这个工作与功能组件一起工作?

【问题讨论】:

  • 您将如何使用类组件来做到这一点?使用new Inner?无论如何,这是答案所在的问题之一 - 你以错误的方式解决这个问题。提升状态,如果由于某种原因这不是一个选项,那么请查看参考。
  • @BrianThompson 有了类组件,我想我可以这样做:const inner = &lt;Inner ... /&gt;; const button = &lt;button onClick={inner.doTheThing()} .../&gt;,对吧? (我还没有尝试过。)但你是对的:我意识到这可能是一个 React 反模式,或者至少不是标准做法。在我的实际用例中,我包装了一个现成的组件来执行我需要的doTheThing;不写doTheThing自己,这是我在这里试图避免的,我不知道如何在不暴露这样的方法的情况下解决它。
  • 不,这也不适用于类组件。一旦你添加了 JSX 语法(正如你应该做的那样),你使用的不是一个类实例,而是一个具有该类的 type 的 React 元素。如果您无法访问具有所需功能的组件,并且它还没有以某种方式公开,那么就没有办法获得它。

标签: javascript reactjs typescript react-functional-component


【解决方案1】:

您可以传递一个 ref,然后将 doTheThing 引用存储在那里。

import { MutableRefObject, useRef, useState } from "react";

interface Inner {
  foo: string;
  dRef: MutableRefObject<{ doTheThing: () => void } | undefined>;
}

function Inner(props: Inner) {
  const [foo, setFoo] = useState<string>(props.foo + "baz");

  function doTheThing() {
    console.log(`doin' that ${foo} thing`);
  }

  props.dRef.current = { doTheThing };

  return <div>{props.foo}</div>;
}

export function Outer() {
  const dRef = useRef<{ doTheThing: () => void }>();
  const inner = <Inner foo="bar" dRef={dRef} />;

  return (
    <>
      <button onClick={() => dRef.current?.doTheThing()}>Do That Thing</button>
      {inner}
    </>
  );
}

【讨论】:

  • 您能否简要介绍一下引用可以访问Inner 状态变量的情况?
  • 查看更新的答案
  • 啊,酷。我的部分问题是试图将一个名为ref 的道具传递给Inner;看起来您正在使用 dRef 以避免与 React 关键字发生冲突。
  • 如果你真的想把它命名为ref,那么你需要使用forwardRef来正确处理它。
猜你喜欢
  • 2020-03-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 2020-05-04
  • 2020-07-23
  • 2019-08-06
  • 1970-01-01
  • 2021-05-13
相关资源
最近更新 更多