如何在React和Typescript中全局存储ref

问题描述 投票:0回答:1

我有很多特定组件的实例,我们称之为<Item>。当悬停在任何<Item>上时,(相当复杂和动态的)工具提示应出现在项目的位置。

当我使用semantic-ui-react时,我选择的工具是使用Popup来显示工具提示。使用弹出窗口的一种方法是为它们提供触发器组件(可能是我的<Item>)和内容组件,它将自动显示在触发器组件周围的特定位置。但后来我的每个项目都有一个Popup实例,这显着增加了我的应用程序的响应时间,因为即使我现在不需要它们,也必须创建所有Popups。

使用Popup的另一种方法是通过其context属性为它提供一个ref,它将在该DOM节点处打开。所以我想使用这个机制只有一个Popup,当我将鼠标悬停在context上时,它会接收到<Item>属性的动态更新。

要做到这一点,我需要将当前的<Item> ref传递给Popup。由于我有一个深度嵌套的应用程序,我选择使用https://github.com/diegohaz/constate在全局共享状态。

不幸的是,共享ref似乎不起作用。每当我尝试从共享上下文中读取它时,它都是null。

请看一下这里的简单示例:https://codesandbox.io/s/pplw689627

虽然我可以在调试器中看到tooltipTarget是在onMouseEnter中写的,当它在<Tooltip>组件中读取时,它总是为空。

我有什么想法我做错了吗?

我愿意接受不同的建议,但如果可能的话,我更愿意使用Semantic的Popup来保持一致的视觉风格。


更新:

Tom Finneys的答案在上面的沙箱中工作,遗憾的是我在我的实际环境中使用的是Typescript,并且它在那里无法正常工作。我在这个沙箱中找到了一个有效的解决方案:https://codesandbox.io/s/7143r32klj

主要问题是currentRefObject<T>属性是readonly。这可以防止您编写如下上下文:

export function useTooltip() {
  const [tooltipRecipe, setTooltipRecipe] = React.useState<string | undefined>(
    undefined
  );
  let tooltipTarget = React.useRef<HTMLElement>(null);
  const setTooltipTarget = (target: HTMLElement | null) => {
    dummy.current = target;
  };
  return { tooltipRecipe, tooltipTarget, setTooltipRecipe, setTooltipTarget };
}

setTooltipTarget不会编译。

我现在能够让它工作的唯一方法是将RefObject<T>转换为本地类型,其中current不是只读的。这是一个非常黑客但它的工作原理。查看沙箱中的解决方案。


实际上这里正在讨论这个问题:https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065

reactjs typescript semantic-ui-react
1个回答
0
投票

你的问题源于试图改变组件体内的tooltipTarget ref。您应该在上下文中声明另一个可以调用的setter函数来更改ref的当前值。

我在沙箱里捅了一下:https://codesandbox.io/s/p6pknz837?fontsize=14

© www.soinside.com 2019 - 2024. All rights reserved.