如何在 Solid.js 中使用 Ref?

huangapple go评论53阅读模式
英文:

How to use Ref in Solid.js?

问题

所以我正在学习并开始尝试使用Solid.js,我想知道在Solid.js中如何处理引用(ref),就像在React中使用useRef一样。

我查看了文档,尝试了类似以下的方式:

let navigationOuterRef: HTMLDivElement;
let navigationRef: HTMLUListElement;

const MenuNavbar = (props: { layoutDatas: LayoutNavigation[] }) => {
  
  const [priorityItems, setPriorityItems] = createSignal<LayoutNavigation[]>(props.layoutDatas);
  
  //....

  return (
    <div ref={navigationOuterRef} class="....">
      <ul ref={navigationRef} class="...">
        <For each={priorityItems()}>
          {(labelName) => (
            <li class="flex items-center cursor-pointer">
              {labelName.label}
            </li>
          )}
        </For>
      </ul>
    //...

它能工作... 但是我得到了以下警告信息:

computations created outside a createRoot or render will never be disposed

所以我认为问题在于我在组件外部创建了引用,因此在没有适当上下文的情况下,它不能在卸载时被处理,但是如果我将引用声明移到组件内部,TypeScript会报以下错误:

Variable 'navigationOuterRef' is used before being assigned.

所以我做错了什么,正确的方法是什么?

英文:

So i am learning and start play around with Solid.js, and I want to know how do we handle ref in solid.js like useRef in react.

I check the doc I try something like this:

      let navigationOuterRef: HTMLDivElement
      let navigationRef: HTMLUListElement
    
     const MenuNavbar = (props: {layoutDatas: LayoutNavigation[]}) =&gt; {
        
       const [priorityItems, setPriorityItems] = createSignal&lt;LayoutNavigation[]&gt;(props.layoutDatas);
      
      //....
    
      return (
        &lt;div ref={navigationOuterRef} class=&quot;....&quot;&gt;
          &lt;ul ref={navigationRef} class=&quot;...&quot;&gt;
            &lt;For each={priorityItems()}&gt;
              {(labelName) =&gt; (
                &lt;li class=&quot;flex items-center cursor-pointer&quot;&gt;
                  {labelName.label}
                &lt;/li&gt;
              )}
            &lt;/For&gt;
          &lt;/ul&gt;
        //...

it work... but I got the warning message like

> computations created outside a createRoot or render will never be disposed

So I think the issue is the fact i create the ref outside the component so without a proper context it cannot be disposed if unmounted, but if i moved the ref declaration in the component I have this error in TS

> Variable 'navigationOuterRef' is used before being assigned.

so what I am doing wrong and what is the right approach ?

答案1

得分: 2

是的,组件要求您在适当的拥有者下运行它们,即render函数或通过createRoot函数或另一个组件创建的根组件。这是为了构建一个所有权图,显示谁拥有谁的图表,以便当组件被销毁时,其资源将被清理。因此,警告消息与引用无关,而与在响应性上下文之外创建的组件有关。

除此之外,引用是底层DOM节点的句柄。它们有两种形式:变量和函数。

变量形式要求您使用onMount钩子,因为当组件加载时,引用将未定义,仅在渲染阶段完成后,它们才指向实际的DOM元素。

let ref;

console.log(ref); // undefined

onMount(() => console.log(ref)); // div

<div ref={ref} />

之所以不能立即使用它们,是因为Solid在构建DOM树时执行赋值操作。

<div ref={el => ref = el} />

变量形式基本上是函数形式的语法糖。

由于引用最初不可用,因此引用元素的正确类型是:

let navigationOuterRef: HTMLDivElement | undefined;

如果不使用undefined,将会出现类型错误:

变量'X'在分配之前被使用

函数形式在DOM节点可用时立即接收DOM元素:

function handleRef(ref: HTMLDivElement) {
  console.log(ref); // div
}

<div ref={handleRef} />

编译后的代码在创建DOM树时调用引用函数。

https://www.solidjs.com/docs/latest#ref

英文:

Yes, components requires you to run them under a proper owner, that is either render function, or a root created via createRoot function or another component. This is needed to build an ownership graph, a graph that show who owns whom so that when a component is disposed, its resources will be cleaned up. So, the warning message is nothing to do with refs, but about components created outside a reactive context.

Other than that refs are handles to underlying DOM nodes. They come in two flavors: variables and functions.

Variable forms requires you to use onMount hooks because when components are loaded, ref will be undefined, only after render phase completes they point to the actual DOM element.

let ref;

console.log(ref); // undefined

onMount(() =&gt; console.log(ref)); // div

&lt;div ref={ref} /&gt;

Why they are not available immediately is because Solid runs the assignment operation while building the DOM tree.

&lt;div ref={el =&gt; ref=el} /&gt; 

Variable form is basically a syntax sugar for the function form.

Since ref is not available initially, the correct type of the ref element is:

let navigationOuterRef: HTMLDivElement | undefined;

If you do not put undefined, you will have the type error:

Variable &#39;X&#39; is used before being assigned

Function form receives the DOM element as soon as the DOM node becomes available:

function handleRef(ref: HTMLDivElement) {
  console.log(ref); // div
}

&lt;div ref={handleRef} /&gt;

Compiled code invokes the ref function while creating the DOM tree.

https://www.solidjs.com/docs/latest#ref

huangapple
  • 本文由 发表于 2023年7月12日 22:04:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76671464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定